diff --git a/.travis.yml b/.travis.yml index b4c589c9d0f..071c67cf91f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,7 @@ dist: trusty language: node_js addons: firefox: 'latest' - apt: - sources: - - google-chrome - packages: - - google-chrome-stable + chrome: stable node_js: - '11.6' diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f39c433e9..63a932dff14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ +### 1.0.4 (Feb 5, 2020) + +Bug fixes + +### Fixes + +* Reset `referenceSpace` and controllers list when entering / exiting VR (#4406) @AG-LucidWeb @Artyom17 @dmarcos +* Fix WebXR buttons mapping for Oculus Go controller @dmarcos +* Properly remove `selectstart` / `selectend` event listeners when XR session ends @DougReeder +* Apply handedness orientation directly to the hands model (#4388) @dbradleyfl @dala00 @dmarcos +* Set tracked-controls `armModel` default to false (#4405) @dmarcos +* Set camera entity `matrixAutoupdate` to false only for the WebXR case (#4383) @liewol @dmarcos +* Check if headset is connected when ignoring `mousedown` events (#4380) @AG-LucidWeb @dmarcos +* Get rid of invalid character in TRHEE build (#4428) @kennardconsulting @dmarcos + +### Enhancements + +* Add dithering property in materials component (#4433) @Firepal +* Add Magic Leap Controller Support @atarng-magicleap +* New high poly, low poly and toon styles for `hand-controls` @arturitu +* Listens to WebXR `selectstart` / `selectstart` and reemits as mousedown / mouseup. Simple screen input for AR experiences (fix #4407) @dmarcos +* Use full hash in dependencies to comply with pnpm @pleku +* Add color property to `hand-controls` @arturitu +* Docs improvements @d2s @ChicagoDev @dirkk0 @omgitsraven @dmarcos +* Add API to set WebXR far and near camera planes (#4387) @DougReeder + + ### 1.0.3 (Dec 30, 2019) +Bug fixes + ### Fixes * Add support for Gear VR controller over WebXR (@Artyom17, @dmarcos) diff --git a/README.md b/README.md index 98dfed1a1d8..1098aa05003 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ and publishing now, remix the starter example on: ```html - + @@ -119,7 +119,7 @@ and publishing now, remix the starter example on: ``` With A-Frame's [entity-component -architecture](https://aframe.io/docs/1.0.3/introduction/entity-component-system.html), we can drop in community +architecture](https://aframe.io/docs/1.0.4/introduction/entity-component-system.html), we can drop in community components from the ecosystem (e.g., ocean, physics) and plug them into our objects straight from HTML: @@ -128,7 +128,7 @@ objects straight from HTML: ```html - + @@ -159,11 +159,11 @@ objects straight from HTML: ### Builds -To use the latest stable build of A-Frame, include [`aframe.min.js`](https://aframe.io/releases/1.0.3/aframe.min.js): +To use the latest stable build of A-Frame, include [`aframe.min.js`](https://aframe.io/releases/1.0.4/aframe.min.js): ```js - + ``` diff --git a/dist/README.md b/dist/README.md index 8d20d52ce69..ceee25db196 100644 --- a/dist/README.md +++ b/dist/README.md @@ -8,7 +8,7 @@ script below from the [jsdelivr CDN](https://www.jsdelivr.com/): ```html - + diff --git a/dist/aframe-master.js b/dist/aframe-master.js index 9bbdfe5ec3b..9b125b768a0 100644 --- a/dist/aframe-master.js +++ b/dist/aframe-master.js @@ -6530,7 +6530,7 @@ module.exports = anime; typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = global || self, factory(global.THREE = {})); -}(this, function (exports) { 'use strict'; +}(this, (function (exports) { 'use strict'; // Polyfills @@ -29876,6 +29876,9 @@ module.exports = anime; cameraVR.layers.enable( 1 ); cameraVR.layers.enable( 2 ); + var _currentDepthNear = null; + var _currentDepthFar = null; + // this.enabled = false; @@ -30041,6 +30044,20 @@ module.exports = anime; this.getCamera = function ( camera ) { + cameraVR.near = cameraR.near = cameraL.near = camera.near; + cameraVR.far = cameraR.far = cameraL.far = camera.far; + if ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) { + + session.updateRenderState( { + depthNear: cameraVR.near, + depthFar: cameraVR.far + } ); + + _currentDepthNear = cameraVR.near; + _currentDepthFar = cameraVR.far; + + } + var parent = camera.parent; var cameras = cameraVR.cameras; var object = poseTarget || camera; @@ -32745,7 +32762,7 @@ module.exports = anime; function materialNeedsLights( material ) { - return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || + return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial || material.isShadowMaterial || ( material.isShaderMaterial && material.lights === true ); @@ -39351,6 +39368,7 @@ module.exports = anime; var Geometries = /*#__PURE__*/Object.freeze({ + __proto__: null, WireframeGeometry: WireframeGeometry, ParametricGeometry: ParametricGeometry, ParametricBufferGeometry: ParametricBufferGeometry, @@ -40379,6 +40397,7 @@ module.exports = anime; var Materials = /*#__PURE__*/Object.freeze({ + __proto__: null, ShadowMaterial: ShadowMaterial, SpriteMaterial: SpriteMaterial, RawShaderMaterial: RawShaderMaterial, @@ -44688,6 +44707,7 @@ module.exports = anime; var Curves = /*#__PURE__*/Object.freeze({ + __proto__: null, ArcCurve: ArcCurve, CatmullRomCurve3: CatmullRomCurve3, CubicBezierCurve: CubicBezierCurve, @@ -57182,7 +57202,7 @@ module.exports = anime; Object.defineProperty(exports, '__esModule', { value: true }); -})); +}))); },{}],58:[function(_dereq_,module,exports){ /** @@ -66716,18 +66736,18 @@ function extend() { },{}],72:[function(_dereq_,module,exports){ module.exports={ "name": "aframe", - "version": "1.0.3", + "version": "1.0.4", "description": "A web framework for building virtual reality experiences.", "homepage": "https://aframe.io/", "main": "dist/aframe-master.js", "scripts": { "browserify": "browserify src/index.js -s 'AFRAME' -p browserify-derequire", - "build": "shx mkdir -p build/ && npm run browserify -- --debug -t [envify --INSPECTOR_VERSION dev] -o build/aframe.js", + "build": "shx mkdir -p build/ && npm run browserify -- --debug -t [ envify --INSPECTOR_VERSION dev ] -o build/aframe.js", "codecov": "codecov", "dev": "npm run build && cross-env INSPECTOR_VERSION=dev node ./scripts/budo -t envify", "dist": "node scripts/updateVersionLog.js && npm run dist:min && npm run dist:max", "dist:max": "npm run browserify -s -- --debug | exorcist dist/aframe-master.js.map > dist/aframe-master.js", - "dist:min": "npm run browserify -s -- --debug -p [minifyify --map aframe-master.min.js.map --output dist/aframe-master.min.js.map] -o dist/aframe-master.min.js", + "dist:min": "npm run browserify -s -- --debug -p [ minifyify --map aframe-master.min.js.map --output dist/aframe-master.min.js.map ] -o dist/aframe-master.min.js", "docs": "markserv --dir docs --port 9001", "preghpages": "node ./scripts/preghpages.js", "ghpages": "ghpages -p gh-pages/", @@ -66735,7 +66755,7 @@ module.exports={ "lint:fix": "semistandard --fix", "precommit": "npm run lint", "prepush": "node scripts/testOnlyCheck.js", - "prerelease": "cross-env node scripts/release.js 1.0.2 1.0.3", + "prerelease": "node scripts/release.js 1.0.3 1.0.4", "start": "npm run dev", "start:https": "cross-env SSL=true npm run dev", "test": "karma start ./tests/karma.conf.js", @@ -66763,8 +66783,8 @@ module.exports={ "present": "0.0.6", "promise-polyfill": "^3.1.0", "super-animejs": "^3.1.0", - "super-three": "^0.111.5", - "three-bmfont-text": "dmarcos/three-bmfont-text#1babdf8507", + "super-three": "^0.111.6", + "three-bmfont-text": "dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e", "webvr-polyfill": "^0.10.10" }, "devDependencies": { @@ -67472,7 +67492,7 @@ function isRawProperty (data) { data.property.startsWith(STRING_OBJECT3D); } -},{"../core/component":126,"../lib/three":174,"../utils":199,"super-animejs":56}],74:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils":200,"super-animejs":56}],74:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); @@ -67564,7 +67584,7 @@ module.exports.Component = registerComponent('camera', { } }); -},{"../core/component":126,"../lib/three":174}],75:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175}],75:[function(_dereq_,module,exports){ /* global THREE */ var registerComponent = _dereq_('../core/component').registerComponent; var utils = _dereq_('../utils/'); @@ -67591,6 +67611,11 @@ var CANVAS_EVENTS = { UP: ['mouseup', 'touchend'] }; +var WEBXR_EVENTS = { + DOWN: ['selectstart'], + UP: ['selectend'] +}; + var CANVAS_HOVER_CLASS = 'a-mouse-cursor-hover'; /** @@ -67640,6 +67665,7 @@ module.exports.Component = registerComponent('cursor', { this.onIntersection = bind(this.onIntersection, this); this.onIntersectionCleared = bind(this.onIntersectionCleared, this); this.onMouseMove = bind(this.onMouseMove, this); + this.onEnterVR = bind(this.onEnterVR, this); }, update: function (oldData) { @@ -67698,6 +67724,7 @@ module.exports.Component = registerComponent('cursor', { el.addEventListener('raycaster-intersection-cleared', this.onIntersectionCleared); el.sceneEl.addEventListener('rendererresize', this.updateCanvasBounds); + el.sceneEl.addEventListener('enter-vr', this.onEnterVR); window.addEventListener('resize', this.updateCanvasBounds); window.addEventListener('scroll', this.updateCanvasBounds); @@ -67733,6 +67760,7 @@ module.exports.Component = registerComponent('cursor', { canvas.removeEventListener('touchmove', this.onMouseMove); el.sceneEl.removeEventListener('rendererresize', this.updateCanvasBounds); + el.sceneEl.removeEventListener('enter-vr', this.onEnterVR); window.removeEventListener('resize', this.updateCanvasBounds); window.removeEventListener('scroll', this.updateCanvasBounds); }, @@ -67877,6 +67905,18 @@ module.exports.Component = registerComponent('cursor', { this.clearCurrentIntersection(); }, + onEnterVR: function () { + var xrSession = this.el.xrSession; + var self = this; + if (!xrSession) { return; } + WEBXR_EVENTS.DOWN.forEach(function (downEvent) { + xrSession.addEventListener(downEvent, self.onCursorDown); + }); + WEBXR_EVENTS.UP.forEach(function (upEvent) { + xrSession.addEventListener(upEvent, self.onCursorUp); + }); + }, + setIntersection: function (intersectedEl, intersection) { var cursorEl = this.el; var data = this.data; @@ -67963,7 +68003,7 @@ module.exports.Component = registerComponent('cursor', { } }); -},{"../core/component":126,"../utils/":199}],76:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200}],76:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -68143,7 +68183,7 @@ module.exports.Component = registerComponent('daydream-controls', { } }); -},{"../core/component":126,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],77:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],77:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -68359,7 +68399,7 @@ module.exports.Component = registerComponent('gearvr-controls', { } }); -},{"../core/component":126,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],78:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],78:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -68412,7 +68452,6 @@ module.exports.Component = registerComponent('generic-tracked-controller-control mapping: INPUT_MAPPING, bindMethods: function () { - this.onModelLoaded = bind(this.onModelLoaded, this); this.onControllersUpdate = bind(this.onControllersUpdate, this); this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); @@ -68439,7 +68478,6 @@ module.exports.Component = registerComponent('generic-tracked-controller-control el.addEventListener('buttonup', this.onButtonUp); el.addEventListener('touchstart', this.onButtonTouchStart); el.addEventListener('touchend', this.onButtonTouchEnd); - el.addEventListener('model-loaded', this.onModelLoaded); el.addEventListener('axismove', this.onAxisMoved); this.controllerEventsActive = true; }, @@ -68523,7 +68561,7 @@ module.exports.Component = registerComponent('generic-tracked-controller-control } }); -},{"../core/component":126,"../utils/bind":193,"../utils/tracked-controls":207}],79:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/bind":194,"../utils/tracked-controls":208}],79:[function(_dereq_,module,exports){ var geometries = _dereq_('../core/geometry').geometries; var geometryNames = _dereq_('../core/geometry').geometryNames; var registerComponent = _dereq_('../core/component').registerComponent; @@ -68602,7 +68640,7 @@ module.exports.Component = registerComponent('geometry', { } }); -},{"../core/component":126,"../core/geometry":127,"../lib/three":174}],80:[function(_dereq_,module,exports){ +},{"../core/component":127,"../core/geometry":128,"../lib/three":175}],80:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); var utils = _dereq_('../utils/'); @@ -68650,14 +68688,18 @@ module.exports.Component = registerComponent('gltf-model', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/":199}],81:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/":200}],81:[function(_dereq_,module,exports){ /* global THREE */ var registerComponent = _dereq_('../core/component').registerComponent; // Found at https://github.com/aframevr/assets. var MODEL_URLS = { - left: 'https://cdn.aframe.io/controllers/hands/leftHand.glb', - right: 'https://cdn.aframe.io/controllers/hands/rightHand.glb' + toonLeft: 'https://cdn.aframe.io/controllers/hands/leftHand.glb', + toonRight: 'https://cdn.aframe.io/controllers/hands/rightHand.glb', + lowPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandLow.glb', + lowPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandLow.glb', + highPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandHigh.glb', + highPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandHigh.glb' }; // Poses. @@ -68697,7 +68739,11 @@ EVENTS[ANIMATIONS.point] = 'pointing'; * @property {string} Hand mapping (`left`, `right`). */ module.exports.Component = registerComponent('hand-controls', { - schema: {default: 'left'}, + schema: { + color: {default: 'white', type: 'color'}, + hand: { default: 'left' }, + handModelStyle: {default: 'lowPoly', oneOf: ['lowPoly', 'highPoly', 'toon']} + }, init: function () { var self = this; @@ -68827,25 +68873,32 @@ module.exports.Component = registerComponent('hand-controls', { update: function (previousHand) { var controlConfiguration; var el = this.el; - var hand = this.data; + var hand = this.data.hand; + var handModelStyle = this.data.handModelStyle; + var handColor = this.data.color; var self = this; // Get common configuration to abstract different vendor controls. controlConfiguration = { hand: hand, - model: false, - orientationOffset: {x: 0, y: 0, z: hand === 'left' ? 90 : -90} + model: false }; // Set model. if (hand !== previousHand) { - this.loader.load(MODEL_URLS[hand], function (gltf) { + var handmodelUrl = MODEL_URLS[handModelStyle + hand.charAt(0).toUpperCase() + hand.slice(1)]; + this.loader.load(handmodelUrl, function (gltf) { var mesh = gltf.scene.children[0]; + var handModelOrientation = hand === 'left' ? Math.PI / 2 : -Math.PI / 2; mesh.mixer = new THREE.AnimationMixer(mesh); self.clips = gltf.animations; el.setObject3D('mesh', mesh); + + var handMaterial = mesh.children[1].material; + handMaterial.color = new THREE.Color(handColor); mesh.position.set(0, 0, 0); - mesh.rotation.set(0, 0, 0); + mesh.rotation.set(0, 0, handModelOrientation); + el.setAttribute('magicleap-controls', controlConfiguration); el.setAttribute('vive-controls', controlConfiguration); el.setAttribute('oculus-touch-controls', controlConfiguration); el.setAttribute('windows-motion-controls', controlConfiguration); @@ -68902,11 +68955,11 @@ module.exports.Component = registerComponent('hand-controls', { */ determineGesture: function () { var gesture; - var isGripActive = this.pressedButtons['grip']; - var isSurfaceActive = this.pressedButtons['surface'] || this.touchedButtons['surface']; - var isTrackpadActive = this.pressedButtons['trackpad'] || this.touchedButtons['trackpad']; - var isTriggerActive = this.pressedButtons['trigger'] || this.touchedButtons['trigger']; - var isABXYActive = this.touchedButtons['AorX'] || this.touchedButtons['BorY']; + var isGripActive = this.pressedButtons.grip; + var isSurfaceActive = this.pressedButtons.surface || this.touchedButtons.surface; + var isTrackpadActive = this.pressedButtons.trackpad || this.touchedButtons.trackpad; + var isTriggerActive = this.pressedButtons.trigger || this.touchedButtons.trigger; + var isABXYActive = this.touchedButtons.AorX || this.touchedButtons.BorY; var isVive = isViveController(this.el.components['tracked-controls']); // Works well with Oculus Touch and Windows Motion Controls, but Vive needs tweaks. @@ -68978,7 +69031,7 @@ module.exports.Component = registerComponent('hand-controls', { if (eventName) { el.emit(eventName); } }, -/** + /** * Play hand animation based on button state. * * @param {string} gesture - Name of the animation as specified by the model. @@ -69046,7 +69099,6 @@ function getGestureEventName (gesture, active) { if (eventName === 'pointing' || eventName === 'pistol') { return eventName + (active ? 'start' : 'end'); } - return; } function isViveController (trackedControls) { @@ -69058,7 +69110,7 @@ function isViveController (trackedControls) { return isVive; } -},{"../core/component":126}],82:[function(_dereq_,module,exports){ +},{"../core/component":127}],82:[function(_dereq_,module,exports){ _dereq_('./animation'); _dereq_('./camera'); _dereq_('./cursor'); @@ -69073,6 +69125,7 @@ _dereq_('./light'); _dereq_('./line'); _dereq_('./link'); _dereq_('./look-controls'); +_dereq_('./magicleap-controls'); _dereq_('./material'); _dereq_('./obj-model'); _dereq_('./oculus-go-controls'); @@ -69105,7 +69158,7 @@ _dereq_('./scene/screenshot'); _dereq_('./scene/stats'); _dereq_('./scene/vr-mode-ui'); -},{"./animation":73,"./camera":74,"./cursor":75,"./daydream-controls":76,"./gearvr-controls":77,"./generic-tracked-controller-controls":78,"./geometry":79,"./gltf-model":80,"./hand-controls":81,"./laser-controls":83,"./light":84,"./line":85,"./link":86,"./look-controls":87,"./material":88,"./obj-model":89,"./oculus-go-controls":90,"./oculus-touch-controls":91,"./position":92,"./raycaster":93,"./rotation":94,"./scale":95,"./scene/background":96,"./scene/debug":97,"./scene/device-orientation-permission-ui":98,"./scene/embedded":99,"./scene/fog":100,"./scene/inspector":101,"./scene/keyboard-shortcuts":102,"./scene/pool":103,"./scene/screenshot":104,"./scene/stats":105,"./scene/vr-mode-ui":106,"./shadow":107,"./sound":108,"./text":109,"./tracked-controls":112,"./tracked-controls-webvr":110,"./tracked-controls-webxr":111,"./visible":113,"./vive-controls":114,"./vive-focus-controls":115,"./wasd-controls":116,"./windows-motion-controls":117}],83:[function(_dereq_,module,exports){ +},{"./animation":73,"./camera":74,"./cursor":75,"./daydream-controls":76,"./gearvr-controls":77,"./generic-tracked-controller-controls":78,"./geometry":79,"./gltf-model":80,"./hand-controls":81,"./laser-controls":83,"./light":84,"./line":85,"./link":86,"./look-controls":87,"./magicleap-controls":88,"./material":89,"./obj-model":90,"./oculus-go-controls":91,"./oculus-touch-controls":92,"./position":93,"./raycaster":94,"./rotation":95,"./scale":96,"./scene/background":97,"./scene/debug":98,"./scene/device-orientation-permission-ui":99,"./scene/embedded":100,"./scene/fog":101,"./scene/inspector":102,"./scene/keyboard-shortcuts":103,"./scene/pool":104,"./scene/screenshot":105,"./scene/stats":106,"./scene/vr-mode-ui":107,"./shadow":108,"./sound":109,"./text":110,"./tracked-controls":113,"./tracked-controls-webvr":111,"./tracked-controls-webxr":112,"./visible":114,"./vive-controls":115,"./vive-focus-controls":116,"./wasd-controls":117,"./windows-motion-controls":118}],83:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var utils = _dereq_('../utils/'); @@ -69126,6 +69179,7 @@ registerComponent('laser-controls', { // Set all controller models. el.setAttribute('daydream-controls', controlsConfiguration); el.setAttribute('gearvr-controls', controlsConfiguration); + el.setAttribute('magicleap-controls', controlsConfiguration); el.setAttribute('oculus-go-controls', controlsConfiguration); el.setAttribute('oculus-touch-controls', controlsConfiguration); el.setAttribute('vive-controls', controlsConfiguration); @@ -69192,6 +69246,10 @@ registerComponent('laser-controls', { cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']} }, + 'magicleap-controls': { + cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']} + }, + 'oculus-go-controls': { cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']}, raycaster: {origin: {x: 0, y: 0.0005, z: 0}} @@ -69217,7 +69275,7 @@ registerComponent('laser-controls', { } }); -},{"../core/component":126,"../utils/":199}],84:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200}],84:[function(_dereq_,module,exports){ var bind = _dereq_('../utils/bind'); var diff = _dereq_('../utils').diff; var debug = _dereq_('../utils/debug'); @@ -69506,7 +69564,7 @@ module.exports.Component = registerComponent('light', { } }); -},{"../core/component":126,"../lib/three":174,"../utils":199,"../utils/bind":193,"../utils/debug":195}],85:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils":200,"../utils/bind":194,"../utils/debug":196}],85:[function(_dereq_,module,exports){ /* global THREE */ var registerComponent = _dereq_('../core/component').registerComponent; @@ -69533,7 +69591,7 @@ module.exports.Component = registerComponent('line', { visible: data.visible }); geometry = this.geometry = new THREE.BufferGeometry(); - geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3)); + geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3)); this.rendererSystem.applyColorCorrection(material.color); this.line = new THREE.Line(geometry, material); @@ -69584,7 +69642,7 @@ function isEqualVec3 (a, b) { return (a.x === b.x && a.y === b.y && a.z === b.z); } -},{"../core/component":126}],86:[function(_dereq_,module,exports){ +},{"../core/component":127}],86:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var registerShader = _dereq_('../core/shader').registerShader; var THREE = _dereq_('../lib/three'); @@ -69956,7 +70014,7 @@ registerShader('portal', { }); /* eslint-enable */ -},{"../core/component":126,"../core/shader":136,"../lib/three":174}],87:[function(_dereq_,module,exports){ +},{"../core/component":127,"../core/shader":137,"../lib/three":175}],87:[function(_dereq_,module,exports){ /* global DeviceOrientationEvent */ var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); @@ -69998,8 +70056,6 @@ module.exports.Component = registerComponent('look-controls', { this.pointerLocked = false; this.setupMouseControls(); this.bindMethods(); - this.el.object3D.matrixAutoUpdate = false; - this.el.object3D.updateMatrix(); this.setupMagicWindowControls(); @@ -70186,8 +70242,6 @@ module.exports.Component = registerComponent('look-controls', { } } return; - } else { - object3D.updateMatrix(); } this.updateMagicWindowOrientation(); @@ -70257,7 +70311,7 @@ module.exports.Component = registerComponent('look-controls', { */ onMouseDown: function (evt) { var sceneEl = this.el.sceneEl; - if (!this.data.enabled || sceneEl.is('vr-mode')) { return; } + if (!this.data.enabled || (sceneEl.is('vr-mode') && sceneEl.checkHeadsetConnected())) { return; } // Handle only primary button. if (evt.button !== 0) { return; } @@ -70345,11 +70399,15 @@ module.exports.Component = registerComponent('look-controls', { * Save pose. */ onEnterVR: function () { - if (!this.el.sceneEl.checkHeadsetConnected()) { return; } + var sceneEl = this.el.sceneEl; + if (!sceneEl.checkHeadsetConnected()) { return; } this.saveCameraPose(); this.el.object3D.position.set(0, 0, 0); this.el.object3D.rotation.set(0, 0, 0); - this.el.object3D.updateMatrix(); + if (sceneEl.hasWebXR) { + this.el.object3D.matrixAutoUpdate = false; + this.el.object3D.updateMatrix(); + } }, /** @@ -70359,6 +70417,7 @@ module.exports.Component = registerComponent('look-controls', { if (!this.el.sceneEl.checkHeadsetConnected()) { return; } this.restoreCameraPose(); this.previousHMDPosition.set(0, 0, 0); + this.el.object3D.matrixAutoUpdate = true; }, /** @@ -70433,7 +70492,187 @@ module.exports.Component = registerComponent('look-controls', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/":199}],88:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/":200}],88:[function(_dereq_,module,exports){ +var bind = _dereq_('../utils/bind'); +var registerComponent = _dereq_('../core/component').registerComponent; + +var trackedControlsUtils = _dereq_('../utils/tracked-controls'); +var checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup; +var emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged; +var onButtonEvent = trackedControlsUtils.onButtonEvent; + +// See Profiles Registry: +// https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/registry +// TODO: Add a more robust system for deriving gamepad name. +var GAMEPAD_ID_PREFIX = 'magicleap'; +var GAMEPAD_ID_SUFFIX = '-one'; +var GAMEPAD_ID_COMPOSITE = GAMEPAD_ID_PREFIX + GAMEPAD_ID_SUFFIX; + +var MAGICLEAP_CONTROLLER_MODEL_GLB_URL = 'https://cdn.aframe.io/controllers/magicleap/magicleap-one-controller.glb'; + +/** + * Button IDs: + * 0 - trigger + * 1 - grip + * 2 - touchpad + * 3 - menu (never dispatched on this layer) + * + * Axis: + * 0 - touchpad x axis + * 1 - touchpad y axis + */ +var INPUT_MAPPING_WEBXR = { + axes: {touchpad: [0, 1]}, + buttons: ['trigger', 'grip', 'touchpad', 'menu'] +}; + +/** + * Magic Leap Controls + * Interface with Magic Leap control and map Gamepad events to controller + * buttons: trigger, grip, touchpad, and menu. + * Load a controller model. + */ +module.exports.Component = registerComponent('magicleap-controls', { + schema: { + hand: {default: 'none'}, + model: {default: true}, + orientationOffset: {type: 'vec3'} + }, + + mapping: INPUT_MAPPING_WEBXR, + + init: function () { + var self = this; + this.controllerPresent = false; + this.lastControllerCheck = 0; + this.onButtonChanged = bind(this.onButtonChanged, this); + this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); }; + this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); }; + this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); }; + this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); }; + this.previousButtonValues = {}; + this.rendererSystem = this.el.sceneEl.systems.renderer; + + this.bindMethods(); + }, + + update: function () { + var data = this.data; + this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2; + }, + + play: function () { + this.checkIfControllerPresent(); + this.addControllersUpdateListener(); + }, + + pause: function () { + this.removeEventListeners(); + this.removeControllersUpdateListener(); + }, + + bindMethods: function () { + this.onModelLoaded = bind(this.onModelLoaded, this); + this.onControllersUpdate = bind(this.onControllersUpdate, this); + this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this); + this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this); + this.onAxisMoved = bind(this.onAxisMoved, this); + }, + + addEventListeners: function () { + var el = this.el; + el.addEventListener('buttonchanged', this.onButtonChanged); + el.addEventListener('buttondown', this.onButtonDown); + el.addEventListener('buttonup', this.onButtonUp); + el.addEventListener('touchstart', this.onButtonTouchStart); + el.addEventListener('touchend', this.onButtonTouchEnd); + el.addEventListener('axismove', this.onAxisMoved); + el.addEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = true; + }, + + removeEventListeners: function () { + var el = this.el; + el.removeEventListener('buttonchanged', this.onButtonChanged); + el.removeEventListener('buttondown', this.onButtonDown); + el.removeEventListener('buttonup', this.onButtonUp); + el.removeEventListener('touchstart', this.onButtonTouchStart); + el.removeEventListener('touchend', this.onButtonTouchEnd); + el.removeEventListener('axismove', this.onAxisMoved); + el.removeEventListener('model-loaded', this.onModelLoaded); + this.controllerEventsActive = false; + }, + + checkIfControllerPresent: function () { + var data = this.data; + checkControllerPresentAndSetup(this, GAMEPAD_ID_COMPOSITE, + {index: this.controllerIndex, hand: data.hand}); + }, + + injectTrackedControls: function () { + var el = this.el; + var data = this.data; + + el.setAttribute('tracked-controls', { + // TODO: verify expected behavior between reserved prefixes. + idPrefix: GAMEPAD_ID_COMPOSITE, + hand: data.hand, + controller: this.controllerIndex, + orientationOffset: data.orientationOffset + }); + + // Load model. + if (!this.data.model) { return; } + this.el.setAttribute('gltf-model', MAGICLEAP_CONTROLLER_MODEL_GLB_URL); + }, + + addControllersUpdateListener: function () { + this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false); + }, + + removeControllersUpdateListener: function () { + this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false); + }, + + onControllersUpdate: function () { + // Note that due to gamepadconnected event propagation issues, we don't rely on events. + this.checkIfControllerPresent(); + }, + + /** + * Rotate the trigger button based on how hard the trigger is pressed. + */ + onButtonChanged: function (evt) { + var button = this.mapping.buttons[evt.detail.id]; + var analogValue; + + if (!button) { return; } + if (button === 'trigger') { + analogValue = evt.detail.state.value; + console.log('analog value of trigger press: ' + analogValue); + } + + // Pass along changed event with button state, using button mapping for convenience. + this.el.emit(button + 'changed', evt.detail.state); + }, + + onModelLoaded: function (evt) { + var controllerObject3D = evt.detail.model; + // our glb scale is too large. + controllerObject3D.scale.set(0.01, 0.01, 0.01); + }, + + onAxisMoved: function (evt) { + emitIfAxesChanged(this, this.mapping.axes, evt); + }, + + updateModel: function (buttonName, evtName) {}, + + setButtonColor: function (buttonName, color) {} + +}); + +},{"../core/component":127,"../utils/bind":194,"../utils/tracked-controls":208}],89:[function(_dereq_,module,exports){ /* global Promise */ var utils = _dereq_('../utils/'); var component = _dereq_('../core/component'); @@ -70467,7 +70706,8 @@ module.exports.Component = registerComponent('material', { transparent: {default: false}, vertexColors: {type: 'string', default: 'none', oneOf: ['face', 'vertex']}, visible: {default: true}, - blending: {default: 'normal', oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply']} + blending: {default: 'normal', oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply']}, + dithering: {default: true} }, init: function () { @@ -70573,6 +70813,7 @@ module.exports.Component = registerComponent('material', { material.vertexColors = parseVertexColors(data.vertexColors); material.visible = data.visible; material.blending = parseBlending(data.blending); + material.dithering = data.dithering; // Check if material needs update. for (oldDataHasKeys in oldData) { break; } @@ -70702,7 +70943,7 @@ function disposeMaterial (material, system) { system.unregisterMaterial(material); } -},{"../core/component":126,"../core/shader":136,"../lib/three":174,"../utils/":199}],89:[function(_dereq_,module,exports){ +},{"../core/component":127,"../core/shader":137,"../lib/three":175,"../utils/":200}],90:[function(_dereq_,module,exports){ var debug = _dereq_('../utils/debug'); var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); @@ -70805,7 +71046,7 @@ module.exports.Component = registerComponent('obj-model', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/debug":195}],90:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/debug":196}],91:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -70849,14 +71090,8 @@ var INPUT_MAPPING_WEBVR = { * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-go.json */ var INPUT_MAPPING_WEBXR = { - left: { - axes: {touchpad: [0, 1]}, - buttons: ['trigger', 'none', 'touchpad'] - }, - right: { - axes: {touchpad: [0, 1]}, - buttons: ['trigger', 'none', 'touchpad'] - } + axes: {touchpad: [0, 1]}, + buttons: ['trigger', 'none', 'touchpad'] }; var INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR; @@ -71019,7 +71254,7 @@ module.exports.Component = registerComponent('oculus-go-controls', { } }); -},{"../core/component":126,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],91:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],92:[function(_dereq_,module,exports){ var bind = _dereq_('../utils/bind'); var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); @@ -71346,7 +71581,7 @@ module.exports.Component = registerComponent('oculus-touch-controls', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],92:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],93:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; module.exports.Component = registerComponent('position', { @@ -71364,7 +71599,7 @@ module.exports.Component = registerComponent('position', { } }); -},{"../core/component":126}],93:[function(_dereq_,module,exports){ +},{"../core/component":127}],94:[function(_dereq_,module,exports){ /* global MutationObserver */ var registerComponent = _dereq_('../core/component').registerComponent; @@ -71799,7 +72034,7 @@ function copyArray (a, b) { } } -},{"../core/component":126,"../lib/three":174,"../utils/":199}],94:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/":200}],95:[function(_dereq_,module,exports){ var degToRad = _dereq_('../lib/three').Math.degToRad; var registerComponent = _dereq_('../core/component').registerComponent; @@ -71822,7 +72057,7 @@ module.exports.Component = registerComponent('rotation', { } }); -},{"../core/component":126,"../lib/three":174}],95:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175}],96:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; // Avoids triggering a zero-determinant which makes object3D matrix non-invertible. @@ -71849,7 +72084,7 @@ module.exports.Component = registerComponent('scale', { } }); -},{"../core/component":126}],96:[function(_dereq_,module,exports){ +},{"../core/component":127}],97:[function(_dereq_,module,exports){ /* global THREE */ var register = _dereq_('../../core/component').registerComponent; @@ -71869,14 +72104,14 @@ module.exports.Component = register('background', { } }); -},{"../../core/component":126}],97:[function(_dereq_,module,exports){ +},{"../../core/component":127}],98:[function(_dereq_,module,exports){ var register = _dereq_('../../core/component').registerComponent; module.exports.Component = register('debug', { schema: {default: true} }); -},{"../../core/component":126}],98:[function(_dereq_,module,exports){ +},{"../../core/component":127}],99:[function(_dereq_,module,exports){ /* global DeviceOrientationEvent, location */ var registerComponent = _dereq_('../../core/component').registerComponent; var utils = _dereq_('../../utils/'); @@ -72074,7 +72309,7 @@ function createDialog (text, buttonsContainerEl) { return modalContainer; } -},{"../../constants/":118,"../../core/component":126,"../../utils/":199}],99:[function(_dereq_,module,exports){ +},{"../../constants/":119,"../../core/component":127,"../../utils/":200}],100:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../../core/component').registerComponent; /** @@ -72099,7 +72334,7 @@ module.exports.Component = registerComponent('embedded', { }); -},{"../../core/component":126}],100:[function(_dereq_,module,exports){ +},{"../../core/component":127}],101:[function(_dereq_,module,exports){ var register = _dereq_('../../core/component').registerComponent; var THREE = _dereq_('../../lib/three'); var debug = _dereq_('../../utils/debug'); @@ -72172,7 +72407,7 @@ function getFog (data) { return fog; } -},{"../../core/component":126,"../../lib/three":174,"../../utils/debug":195}],101:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../lib/three":175,"../../utils/debug":196}],102:[function(_dereq_,module,exports){ (function (process){ /* global AFRAME */ var AFRAME_INJECTED = _dereq_('../../constants').AFRAME_INJECTED; @@ -72292,7 +72527,7 @@ module.exports.Component = registerComponent('inspector', { }).call(this,_dereq_('_process')) -},{"../../../package":72,"../../constants":118,"../../core/component":126,"../../utils/":199,"_process":49}],102:[function(_dereq_,module,exports){ +},{"../../../package":72,"../../constants":119,"../../core/component":127,"../../utils/":200,"_process":49}],103:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../../core/component').registerComponent; var shouldCaptureKeyEvent = _dereq_('../../utils/').shouldCaptureKeyEvent; @@ -72331,7 +72566,7 @@ module.exports.Component = registerComponent('keyboard-shortcuts', { } }); -},{"../../core/component":126,"../../utils/":199}],103:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../utils/":200}],104:[function(_dereq_,module,exports){ var debug = _dereq_('../../utils/debug'); var registerComponent = _dereq_('../../core/component').registerComponent; @@ -72449,7 +72684,7 @@ module.exports.Component = registerComponent('pool', { } }); -},{"../../core/component":126,"../../utils/debug":195}],104:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../utils/debug":196}],105:[function(_dereq_,module,exports){ /* global ImageData, URL */ var registerComponent = _dereq_('../../core/component').registerComponent; var THREE = _dereq_('../../lib/three'); @@ -72714,7 +72949,7 @@ module.exports.Component = registerComponent('screenshot', { } }); -},{"../../core/component":126,"../../lib/three":174}],105:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../lib/three":175}],106:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../../core/component').registerComponent; var RStats = _dereq_('../../../vendor/rStats'); var utils = _dereq_('../../utils'); @@ -72794,7 +73029,7 @@ function createStats (scene) { }); } -},{"../../../vendor/rStats":210,"../../../vendor/rStats.extras":209,"../../core/component":126,"../../lib/rStatsAframe":173,"../../utils":199}],106:[function(_dereq_,module,exports){ +},{"../../../vendor/rStats":211,"../../../vendor/rStats.extras":210,"../../core/component":127,"../../lib/rStatsAframe":174,"../../utils":200}],107:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../../core/component').registerComponent; var constants = _dereq_('../../constants/'); var utils = _dereq_('../../utils/'); @@ -73062,7 +73297,7 @@ function applyStickyHoverFix (buttonEl) { }); } -},{"../../constants/":118,"../../core/component":126,"../../utils/":199}],107:[function(_dereq_,module,exports){ +},{"../../constants/":119,"../../core/component":127,"../../utils/":200}],108:[function(_dereq_,module,exports){ var component = _dereq_('../core/component'); var THREE = _dereq_('../lib/three'); var bind = _dereq_('../utils/bind'); @@ -73116,7 +73351,7 @@ module.exports.Component = registerComponent('shadow', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/bind":193}],108:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/bind":194}],109:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var debug = _dereq_('../utils/debug'); var THREE = _dereq_('../lib/three'); @@ -73367,7 +73602,7 @@ module.exports.Component = registerComponent('sound', { } }); -},{"../core/component":126,"../lib/three":174,"../utils/debug":195}],109:[function(_dereq_,module,exports){ +},{"../core/component":127,"../lib/three":175,"../utils/debug":196}],110:[function(_dereq_,module,exports){ var createTextGeometry = _dereq_('three-bmfont-text'); var loadBMFont = _dereq_('load-bmfont'); @@ -73852,7 +74087,7 @@ function PromiseCache () { }; } -},{"../core/component":126,"../core/shader":136,"../lib/three":174,"../utils/":199,"load-bmfont":37,"three-bmfont-text":62}],110:[function(_dereq_,module,exports){ +},{"../core/component":127,"../core/shader":137,"../lib/three":175,"../utils/":200,"load-bmfont":37,"three-bmfont-text":62}],111:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var controllerUtils = _dereq_('../utils/tracked-controls'); var DEFAULT_CAMERA_HEIGHT = _dereq_('../constants').DEFAULT_CAMERA_HEIGHT; @@ -73897,7 +74132,7 @@ module.exports.Component = registerComponent('tracked-controls-webvr', { idPrefix: {type: 'string', default: ''}, orientationOffset: {type: 'vec3'}, // Arm model parameters when not 6DoF. - armModel: {default: true}, + armModel: {default: false}, headElement: {type: 'selector'} }, @@ -74189,7 +74424,7 @@ module.exports.Component = registerComponent('tracked-controls-webvr', { } }); -},{"../constants":118,"../core/component":126,"../lib/three":174,"../utils/tracked-controls":207}],111:[function(_dereq_,module,exports){ +},{"../constants":119,"../core/component":127,"../lib/three":175,"../utils/tracked-controls":208}],112:[function(_dereq_,module,exports){ var controllerUtils = _dereq_('../utils/tracked-controls'); var registerComponent = _dereq_('../core/component').registerComponent; @@ -74253,9 +74488,18 @@ module.exports.Component = registerComponent('tracked-controls-webxr', { sceneEl.xrSession.removeEventListener('selectend', this.emitButtonUpEvent); }, + isControllerPresent: function (evt) { + if (!this.controller || this.controller.gamepad) { return false; } + if (evt.inputSource.handedness !== 'none' && + evt.inputSource.handedness !== this.data.hand) { + return false; + } + return true; + }, + emitButtonDownEvent: function (evt) { - if (!this.controller || evt.inputSource.handedness !== this.data.hand) { return; } - if (this.controller.gamepad) { return; } + if (!this.isControllerPresent(evt)) { return; } + this.selectEventDetails.state.pressed = true; this.el.emit('buttondown', this.selectEventDetails); this.el.emit('buttonchanged', this.selectEventDetails); @@ -74263,8 +74507,8 @@ module.exports.Component = registerComponent('tracked-controls-webxr', { }, emitButtonUpEvent: function (evt) { - if (!this.controller || evt.inputSource.handedness !== this.data.hand) { return; } - if (this.controller.gamepad) { return; } + if (!this.isControllerPresent(evt)) { return; } + this.selectEventDetails.state.pressed = false; this.el.emit('buttonup', this.selectEventDetails); this.el.emit('buttonchanged', this.selectEventDetails); @@ -74290,7 +74534,7 @@ module.exports.Component = registerComponent('tracked-controls-webxr', { tick: function () { var sceneEl = this.el.sceneEl; - if (!this.controller || !sceneEl.frame) { return; } + if (!this.controller || !sceneEl.frame || !this.system.referenceSpace) { return; } this.pose = sceneEl.frame.getPose(this.controller.targetRaySpace, this.system.referenceSpace); this.updatePose(); this.updateButtons(); @@ -74436,7 +74680,7 @@ module.exports.Component = registerComponent('tracked-controls-webxr', { } }); -},{"../core/component":126,"../utils/tracked-controls":207}],112:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/tracked-controls":208}],113:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; /** @@ -74458,7 +74702,7 @@ module.exports.Component = registerComponent('tracked-controls', { idPrefix: {type: 'string', default: ''}, orientationOffset: {type: 'vec3'}, // Arm model parameters when not 6DoF. - armModel: {default: true}, + armModel: {default: false}, headElement: {type: 'selector'}, iterateControllerProfiles: {default: false} }, @@ -74479,7 +74723,7 @@ module.exports.Component = registerComponent('tracked-controls', { } }); -},{"../core/component":126}],113:[function(_dereq_,module,exports){ +},{"../core/component":127}],114:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; /** @@ -74493,7 +74737,7 @@ module.exports.Component = registerComponent('visible', { } }); -},{"../core/component":126}],114:[function(_dereq_,module,exports){ +},{"../core/component":127}],115:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -74754,7 +74998,7 @@ module.exports.Component = registerComponent('vive-controls', { } }); -},{"../core/component":126,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],115:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],116:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -74936,7 +75180,7 @@ module.exports.Component = registerComponent('vive-focus-controls', { } }); -},{"../core/component":126,"../utils/bind":193,"../utils/tracked-controls":207}],116:[function(_dereq_,module,exports){ +},{"../core/component":127,"../utils/bind":194,"../utils/tracked-controls":208}],117:[function(_dereq_,module,exports){ var KEYCODE_TO_CODE = _dereq_('../constants').keyboardevent.KEYCODE_TO_CODE; var registerComponent = _dereq_('../core/component').registerComponent; var THREE = _dereq_('../lib/three'); @@ -75148,7 +75392,7 @@ function isEmptyObject (keys) { return true; } -},{"../constants":118,"../core/component":126,"../lib/three":174,"../utils/":199}],117:[function(_dereq_,module,exports){ +},{"../constants":119,"../core/component":127,"../lib/three":175,"../utils/":200}],118:[function(_dereq_,module,exports){ /* global THREE */ var registerComponent = _dereq_('../core/component').registerComponent; var bind = _dereq_('../utils/bind'); @@ -75321,7 +75565,8 @@ module.exports.Component = registerComponent('windows-motion-controls', { checkIfControllerPresent: function () { checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, { hand: this.data.hand, - index: this.data.pair + index: this.data.pair, + iterateControllerProfiles: true }); }, @@ -75633,7 +75878,7 @@ module.exports.Component = registerComponent('windows-motion-controls', { } }); -},{"../constants":118,"../core/component":126,"../utils/":199,"../utils/bind":193,"../utils/tracked-controls":207}],118:[function(_dereq_,module,exports){ +},{"../constants":119,"../core/component":127,"../utils/":200,"../utils/bind":194,"../utils/tracked-controls":208}],119:[function(_dereq_,module,exports){ module.exports = { AFRAME_INJECTED: 'aframe-injected', DEFAULT_CAMERA_HEIGHT: 1.6, @@ -75641,7 +75886,7 @@ module.exports = { keyboardevent: _dereq_('./keyboardevent') }; -},{"./keyboardevent":119}],119:[function(_dereq_,module,exports){ +},{"./keyboardevent":120}],120:[function(_dereq_,module,exports){ module.exports = { // Tiny KeyboardEvent.code polyfill. KEYCODE_TO_CODE: { @@ -75656,7 +75901,7 @@ module.exports = { } }; -},{}],120:[function(_dereq_,module,exports){ +},{}],121:[function(_dereq_,module,exports){ var ANode = _dereq_('./a-node'); var bind = _dereq_('../utils/bind'); var debug = _dereq_('../utils/debug'); @@ -75936,7 +76181,7 @@ function getFileNameFromURL (url) { } module.exports.getFileNameFromURL = getFileNameFromURL; -},{"../lib/three":174,"../utils/bind":193,"../utils/debug":195,"./a-node":124,"./a-register-element":125}],121:[function(_dereq_,module,exports){ +},{"../lib/three":175,"../utils/bind":194,"../utils/debug":196,"./a-node":125,"./a-register-element":126}],122:[function(_dereq_,module,exports){ var debug = _dereq_('../utils/debug'); var registerElement = _dereq_('./a-register-element').registerElement; @@ -75986,7 +76231,7 @@ module.exports = registerElement('a-cubemap', { }) }); -},{"../utils/debug":195,"./a-register-element":125}],122:[function(_dereq_,module,exports){ +},{"../utils/debug":196,"./a-register-element":126}],123:[function(_dereq_,module,exports){ var ANode = _dereq_('./a-node'); var COMPONENTS = _dereq_('./component').components; var registerElement = _dereq_('./a-register-element').registerElement; @@ -76920,7 +77165,7 @@ function getRotation (entityEl) { AEntity = registerElement('a-entity', {prototype: proto}); module.exports = AEntity; -},{"../lib/three":174,"../utils/":199,"./a-node":124,"./a-register-element":125,"./component":126}],123:[function(_dereq_,module,exports){ +},{"../lib/three":175,"../utils/":200,"./a-node":125,"./a-register-element":126,"./component":127}],124:[function(_dereq_,module,exports){ var ANode = _dereq_('./a-node'); var registerElement = _dereq_('./a-register-element').registerElement; var components = _dereq_('./component').components; @@ -77036,7 +77281,7 @@ module.exports = registerElement('a-mixin', { }) }); -},{"../utils":199,"./a-node":124,"./a-register-element":125,"./component":126}],124:[function(_dereq_,module,exports){ +},{"../utils":200,"./a-node":125,"./a-register-element":126,"./component":127}],125:[function(_dereq_,module,exports){ /* global CustomEvent */ var registerElement = _dereq_('./a-register-element').registerElement; var isNode = _dereq_('./a-register-element').isNode; @@ -77307,7 +77552,7 @@ module.exports = registerElement('a-node', { }) }); -},{"../utils/":199,"./a-register-element":125}],125:[function(_dereq_,module,exports){ +},{"../utils/":200,"./a-register-element":126}],126:[function(_dereq_,module,exports){ /* ------------------------------------------------------------ ------------- WARNING WARNING WARNING WARNING -------------- @@ -77494,7 +77739,7 @@ function copyProperties (source, destination) { ANode = _dereq_('./a-node'); AEntity = _dereq_('./a-entity'); -},{"./a-entity":122,"./a-node":124,"document-register-element":12}],126:[function(_dereq_,module,exports){ +},{"./a-entity":123,"./a-node":125,"document-register-element":12}],127:[function(_dereq_,module,exports){ /* global Node */ var schema = _dereq_('./schema'); var scenes = _dereq_('./scene/scenes'); @@ -78299,7 +78544,7 @@ function isObjectOrArray (value) { !(value instanceof window.HTMLElement); } -},{"../utils/":199,"./scene/scenes":133,"./schema":135,"./system":137}],127:[function(_dereq_,module,exports){ +},{"../utils/":200,"./scene/scenes":134,"./schema":136,"./system":138}],128:[function(_dereq_,module,exports){ var schema = _dereq_('./schema'); var processSchema = schema.process; @@ -78373,7 +78618,7 @@ module.exports.registerGeometry = function (name, definition) { return NewGeometry; }; -},{"../lib/three":174,"./schema":135}],128:[function(_dereq_,module,exports){ +},{"../lib/three":175,"./schema":136}],129:[function(_dereq_,module,exports){ var coordinates = _dereq_('../utils/coordinates'); var debug = _dereq_('debug'); @@ -78598,7 +78843,7 @@ function isValidDefaultCoordinate (possibleCoordinates, dimensions) { } module.exports.isValidDefaultCoordinate = isValidDefaultCoordinate; -},{"../utils/coordinates":194,"debug":8}],129:[function(_dereq_,module,exports){ +},{"../utils/coordinates":195,"debug":8}],130:[function(_dereq_,module,exports){ /* global Promise, screen, CustomEvent */ var initMetaTags = _dereq_('./metaTags').inject; var initWakelock = _dereq_('./wakelock'); @@ -79190,7 +79435,8 @@ module.exports.AScene = registerElement('a-scene', { alpha: true, antialias: !isMobile, canvas: this.canvas, - logarithmicDepthBuffer: false + logarithmicDepthBuffer: false, + powerPreference: 'high-performance' }; this.maxCanvasSize = {height: 1920, width: 1920}; @@ -79496,7 +79742,7 @@ function setupCanvas (sceneEl) { } module.exports.setupCanvas = setupCanvas; // For testing. -},{"../../lib/three":174,"../../utils/":199,"../a-entity":122,"../a-node":124,"../a-register-element":125,"../system":137,"./loadingScreen":130,"./metaTags":131,"./postMessage":132,"./scenes":133,"./wakelock":134}],130:[function(_dereq_,module,exports){ +},{"../../lib/three":175,"../../utils/":200,"../a-entity":123,"../a-node":125,"../a-register-element":126,"../system":138,"./loadingScreen":131,"./metaTags":132,"./postMessage":133,"./scenes":134,"./wakelock":135}],131:[function(_dereq_,module,exports){ /* global THREE */ var utils = _dereq_('../../utils/'); var styleParser = utils.styleParser; @@ -79590,7 +79836,7 @@ function setupTitle () { sceneEl.appendChild(titleEl); } -},{"../../utils/":199}],131:[function(_dereq_,module,exports){ +},{"../../utils/":200}],132:[function(_dereq_,module,exports){ var constants = _dereq_('../../constants/'); var extend = _dereq_('../../utils').extend; @@ -79671,7 +79917,7 @@ function createTag (tagObj) { return extend(meta, tagObj.attributes); } -},{"../../constants/":118,"../../utils":199}],132:[function(_dereq_,module,exports){ +},{"../../constants/":119,"../../utils":200}],133:[function(_dereq_,module,exports){ var bind = _dereq_('../../utils/bind'); var isIframed = _dereq_('../../utils/').isIframed; @@ -79704,13 +79950,13 @@ function postMessageAPIHandler (event) { } } -},{"../../utils/":199,"../../utils/bind":193}],133:[function(_dereq_,module,exports){ +},{"../../utils/":200,"../../utils/bind":194}],134:[function(_dereq_,module,exports){ /* Scene index for keeping track of created scenes. */ module.exports = []; -},{}],134:[function(_dereq_,module,exports){ +},{}],135:[function(_dereq_,module,exports){ var Wakelock = _dereq_('../../../vendor/wakelock/wakelock'); module.exports = function initWakelock (scene) { @@ -79721,7 +79967,7 @@ module.exports = function initWakelock (scene) { scene.addEventListener('exit-vr', function () { wakelock.release(); }); }; -},{"../../../vendor/wakelock/wakelock":213}],135:[function(_dereq_,module,exports){ +},{"../../../vendor/wakelock/wakelock":214}],136:[function(_dereq_,module,exports){ var utils = _dereq_('../utils/'); var PropertyTypes = _dereq_('./propertyTypes'); @@ -79925,7 +80171,7 @@ function stringifyProperty (value, propDefinition) { } module.exports.stringifyProperty = stringifyProperty; -},{"../utils/":199,"./propertyTypes":128}],136:[function(_dereq_,module,exports){ +},{"../utils/":200,"./propertyTypes":129}],137:[function(_dereq_,module,exports){ var schema = _dereq_('./schema'); var processSchema = schema.process; @@ -80114,7 +80360,7 @@ module.exports.registerShader = function (name, definition) { return NewShader; }; -},{"../lib/three":174,"../utils":199,"./schema":135}],137:[function(_dereq_,module,exports){ +},{"../lib/three":175,"../utils":200,"./schema":136}],138:[function(_dereq_,module,exports){ var components = _dereq_('./component'); var schema = _dereq_('./schema'); var utils = _dereq_('../utils/'); @@ -80272,10 +80518,10 @@ module.exports.registerSystem = function (name, definition) { for (i = 0; i < scenes.length; i++) { scenes[i].initSystem(name); } }; -},{"../utils/":199,"./component":126,"./schema":135}],138:[function(_dereq_,module,exports){ +},{"../utils/":200,"./component":127,"./schema":136}],139:[function(_dereq_,module,exports){ _dereq_('./pivot'); -},{"./pivot":139}],139:[function(_dereq_,module,exports){ +},{"./pivot":140}],140:[function(_dereq_,module,exports){ var registerComponent = _dereq_('../../core/component').registerComponent; var THREE = _dereq_('../../lib/three'); @@ -80324,7 +80570,7 @@ registerComponent('pivot', { } }); -},{"../../core/component":126,"../../lib/three":174}],140:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../lib/three":175}],141:[function(_dereq_,module,exports){ /** * Common mesh defaults, mappings, and transforms. */ @@ -80351,7 +80597,7 @@ module.exports = function getMeshMixin () { }; }; -},{"../../core/component":126,"../../core/shader":136,"../../utils/":199}],141:[function(_dereq_,module,exports){ +},{"../../core/component":127,"../../core/shader":137,"../../utils/":200}],142:[function(_dereq_,module,exports){ _dereq_('./primitives/a-camera'); _dereq_('./primitives/a-cursor'); _dereq_('./primitives/a-curvedimage'); @@ -80367,7 +80613,7 @@ _dereq_('./primitives/a-video'); _dereq_('./primitives/a-videosphere'); _dereq_('./primitives/meshPrimitives'); -},{"./primitives/a-camera":143,"./primitives/a-cursor":144,"./primitives/a-curvedimage":145,"./primitives/a-gltf-model":146,"./primitives/a-image":147,"./primitives/a-light":148,"./primitives/a-link":149,"./primitives/a-obj-model":150,"./primitives/a-sky":151,"./primitives/a-sound":152,"./primitives/a-text":153,"./primitives/a-video":154,"./primitives/a-videosphere":155,"./primitives/meshPrimitives":156}],142:[function(_dereq_,module,exports){ +},{"./primitives/a-camera":144,"./primitives/a-cursor":145,"./primitives/a-curvedimage":146,"./primitives/a-gltf-model":147,"./primitives/a-image":148,"./primitives/a-light":149,"./primitives/a-link":150,"./primitives/a-obj-model":151,"./primitives/a-sky":152,"./primitives/a-sound":153,"./primitives/a-text":154,"./primitives/a-video":155,"./primitives/a-videosphere":156,"./primitives/meshPrimitives":157}],143:[function(_dereq_,module,exports){ var AEntity = _dereq_('../../core/a-entity'); var components = _dereq_('../../core/component').components; var registerElement = _dereq_('../../core/a-register-element').registerElement; @@ -80566,7 +80812,7 @@ function definePrimitive (tagName, defaultComponents, mappings) { } module.exports.definePrimitive = definePrimitive; -},{"../../core/a-entity":122,"../../core/a-register-element":125,"../../core/component":126,"../../utils/":199}],143:[function(_dereq_,module,exports){ +},{"../../core/a-entity":123,"../../core/a-register-element":126,"../../core/component":127,"../../utils/":200}],144:[function(_dereq_,module,exports){ var registerPrimitive = _dereq_('../primitives').registerPrimitive; registerPrimitive('a-camera', { @@ -80590,7 +80836,7 @@ registerPrimitive('a-camera', { } }); -},{"../primitives":142}],144:[function(_dereq_,module,exports){ +},{"../primitives":143}],145:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80625,7 +80871,7 @@ registerPrimitive('a-cursor', utils.extendDeep({}, getMeshMixin(), { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],145:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],146:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80662,7 +80908,7 @@ registerPrimitive('a-curvedimage', utils.extendDeep({}, getMeshMixin(), { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],146:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],147:[function(_dereq_,module,exports){ var registerPrimitive = _dereq_('../primitives').registerPrimitive; registerPrimitive('a-gltf-model', { @@ -80671,7 +80917,7 @@ registerPrimitive('a-gltf-model', { } }); -},{"../primitives":142}],147:[function(_dereq_,module,exports){ +},{"../primitives":143}],148:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80695,7 +80941,7 @@ registerPrimitive('a-image', utils.extendDeep({}, getMeshMixin(), { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],148:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],149:[function(_dereq_,module,exports){ var registerPrimitive = _dereq_('../primitives').registerPrimitive; registerPrimitive('a-light', { @@ -80716,7 +80962,7 @@ registerPrimitive('a-light', { } }); -},{"../primitives":142}],149:[function(_dereq_,module,exports){ +},{"../primitives":143}],150:[function(_dereq_,module,exports){ var registerPrimitive = _dereq_('../primitives').registerPrimitive; registerPrimitive('a-link', { @@ -80733,7 +80979,7 @@ registerPrimitive('a-link', { } }); -},{"../primitives":142}],150:[function(_dereq_,module,exports){ +},{"../primitives":143}],151:[function(_dereq_,module,exports){ var meshMixin = _dereq_('../getMeshMixin')(); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80749,7 +80995,7 @@ registerPrimitive('a-obj-model', utils.extendDeep({}, meshMixin, { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],151:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],152:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80775,7 +81021,7 @@ registerPrimitive('a-sky', utils.extendDeep({}, getMeshMixin(), { mappings: utils.extendDeep({}, meshPrimitives['a-sphere'].prototype.mappings) })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142,"./meshPrimitives":156}],152:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143,"./meshPrimitives":157}],153:[function(_dereq_,module,exports){ var registerPrimitive = _dereq_('../primitives').registerPrimitive; registerPrimitive('a-sound', { @@ -80792,12 +81038,12 @@ registerPrimitive('a-sound', { } }); -},{"../primitives":142}],153:[function(_dereq_,module,exports){ +},{"../primitives":143}],154:[function(_dereq_,module,exports){ // using `definePrimitive` helper. var definePrimitive = _dereq_('../primitives').definePrimitive; definePrimitive('a-text', {text: {anchor: 'align', width: 5}}); -},{"../primitives":142}],154:[function(_dereq_,module,exports){ +},{"../primitives":143}],155:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80821,7 +81067,7 @@ registerPrimitive('a-video', utils.extendDeep({}, getMeshMixin(), { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],155:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],156:[function(_dereq_,module,exports){ var getMeshMixin = _dereq_('../getMeshMixin'); var registerPrimitive = _dereq_('../primitives').registerPrimitive; var utils = _dereq_('../../../utils/'); @@ -80850,7 +81096,7 @@ registerPrimitive('a-videosphere', utils.extendDeep({}, getMeshMixin(), { } })); -},{"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],156:[function(_dereq_,module,exports){ +},{"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],157:[function(_dereq_,module,exports){ /** * Automated mesh primitive registration. */ @@ -80890,7 +81136,7 @@ function unCamelCase (str) { return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); } -},{"../../../core/geometry":127,"../../../utils/":199,"../getMeshMixin":140,"../primitives":142}],157:[function(_dereq_,module,exports){ +},{"../../../core/geometry":128,"../../../utils/":200,"../getMeshMixin":141,"../primitives":143}],158:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -80911,7 +81157,7 @@ registerGeometry('box', { } }); -},{"../core/geometry":127,"../lib/three":174}],158:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],159:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -80931,7 +81177,7 @@ registerGeometry('circle', { } }); -},{"../core/geometry":127,"../lib/three":174}],159:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],160:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -80957,7 +81203,7 @@ registerGeometry('cone', { } }); -},{"../core/geometry":127,"../lib/three":174}],160:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],161:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -80981,7 +81227,7 @@ registerGeometry('cylinder', { } }); -},{"../core/geometry":127,"../lib/three":174}],161:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],162:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -80996,7 +81242,7 @@ registerGeometry('dodecahedron', { } }); -},{"../core/geometry":127,"../lib/three":174}],162:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],163:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81011,7 +81257,7 @@ registerGeometry('icosahedron', { } }); -},{"../core/geometry":127,"../lib/three":174}],163:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],164:[function(_dereq_,module,exports){ _dereq_('./box.js'); _dereq_('./circle.js'); _dereq_('./cone.js'); @@ -81027,7 +81273,7 @@ _dereq_('./torus.js'); _dereq_('./torusKnot.js'); _dereq_('./triangle.js'); -},{"./box.js":157,"./circle.js":158,"./cone.js":159,"./cylinder.js":160,"./dodecahedron.js":161,"./icosahedron.js":162,"./octahedron.js":164,"./plane.js":165,"./ring.js":166,"./sphere.js":167,"./tetrahedron.js":168,"./torus.js":169,"./torusKnot.js":170,"./triangle.js":171}],164:[function(_dereq_,module,exports){ +},{"./box.js":158,"./circle.js":159,"./cone.js":160,"./cylinder.js":161,"./dodecahedron.js":162,"./icosahedron.js":163,"./octahedron.js":165,"./plane.js":166,"./ring.js":167,"./sphere.js":168,"./tetrahedron.js":169,"./torus.js":170,"./torusKnot.js":171,"./triangle.js":172}],165:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81042,7 +81288,7 @@ registerGeometry('octahedron', { } }); -},{"../core/geometry":127,"../lib/three":174}],165:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],166:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81059,7 +81305,7 @@ registerGeometry('plane', { } }); -},{"../core/geometry":127,"../lib/three":174}],166:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],167:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81082,7 +81328,7 @@ registerGeometry('ring', { } }); -},{"../core/geometry":127,"../lib/three":174}],167:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],168:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81106,7 +81352,7 @@ registerGeometry('sphere', { } }); -},{"../core/geometry":127,"../lib/three":174}],168:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],169:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81121,7 +81367,7 @@ registerGeometry('tetrahedron', { } }); -},{"../core/geometry":127,"../lib/three":174}],169:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],170:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81143,7 +81389,7 @@ registerGeometry('torus', { } }); -},{"../core/geometry":127,"../lib/three":174}],170:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],171:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81164,7 +81410,7 @@ registerGeometry('torusKnot', { } }); -},{"../core/geometry":127,"../lib/three":174}],171:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],172:[function(_dereq_,module,exports){ var registerGeometry = _dereq_('../core/geometry').registerGeometry; var THREE = _dereq_('../lib/three'); @@ -81219,7 +81465,7 @@ registerGeometry('triangle', { } }); -},{"../core/geometry":127,"../lib/three":174}],172:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../lib/three":175}],173:[function(_dereq_,module,exports){ // Polyfill `Promise`. window.Promise = window.Promise || _dereq_('promise-polyfill'); @@ -81311,7 +81557,7 @@ _dereq_('./core/a-mixin'); _dereq_('./extras/components/'); _dereq_('./extras/primitives/'); -console.log('A-Frame Version: 1.0.3 (Date 2020-01-01, Commit #5ae949dc)'); +console.log('A-Frame Version: 1.0.4 (Date 2020-02-12, Commit #e949907e)'); console.log('three Version (https://github.com/supermedium/three.js):', pkg.dependencies['super-three']); console.log('WebVR Polyfill Version:', pkg.dependencies['webvr-polyfill']); @@ -81344,7 +81590,7 @@ module.exports = window.AFRAME = { version: pkg.version }; -},{"../package":72,"../vendor/starts-with-polyfill":211,"./components/index":82,"./core/a-assets":120,"./core/a-cubemap":121,"./core/a-entity":122,"./core/a-mixin":123,"./core/a-node":124,"./core/a-register-element":125,"./core/component":126,"./core/geometry":127,"./core/scene/a-scene":129,"./core/scene/scenes":133,"./core/schema":135,"./core/shader":136,"./core/system":137,"./extras/components/":138,"./extras/primitives/":141,"./extras/primitives/getMeshMixin":140,"./extras/primitives/primitives":142,"./geometries/index":163,"./lib/three":174,"./shaders/index":176,"./style/aframe.css":181,"./style/rStats.css":182,"./systems/index":186,"./utils/":199,"./utils/isIOSOlderThan10":201,"custom-event-polyfill":7,"present":48,"promise-polyfill":50,"super-animejs":56,"webvr-polyfill":67}],173:[function(_dereq_,module,exports){ +},{"../package":72,"../vendor/starts-with-polyfill":212,"./components/index":82,"./core/a-assets":121,"./core/a-cubemap":122,"./core/a-entity":123,"./core/a-mixin":124,"./core/a-node":125,"./core/a-register-element":126,"./core/component":127,"./core/geometry":128,"./core/scene/a-scene":130,"./core/scene/scenes":134,"./core/schema":136,"./core/shader":137,"./core/system":138,"./extras/components/":139,"./extras/primitives/":142,"./extras/primitives/getMeshMixin":141,"./extras/primitives/primitives":143,"./geometries/index":164,"./lib/three":175,"./shaders/index":177,"./style/aframe.css":182,"./style/rStats.css":183,"./systems/index":187,"./utils/":200,"./utils/isIOSOlderThan10":202,"custom-event-polyfill":7,"present":48,"promise-polyfill":50,"super-animejs":56,"webvr-polyfill":67}],174:[function(_dereq_,module,exports){ window.aframeStats = function (scene) { var _rS = null; var _scene = scene; @@ -81401,7 +81647,7 @@ if (typeof module === 'object') { }; } -},{}],174:[function(_dereq_,module,exports){ +},{}],175:[function(_dereq_,module,exports){ (function (global){ var THREE = global.THREE = _dereq_('super-three'); @@ -81439,7 +81685,7 @@ module.exports = THREE; }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"../../vendor/DeviceOrientationControls":208,"super-three":57,"super-three/examples/js/loaders/DRACOLoader":58,"super-three/examples/js/loaders/GLTFLoader":59,"super-three/examples/js/loaders/MTLLoader":60,"super-three/examples/js/loaders/OBJLoader":61}],175:[function(_dereq_,module,exports){ +},{"../../vendor/DeviceOrientationControls":209,"super-three":57,"super-three/examples/js/loaders/DRACOLoader":58,"super-three/examples/js/loaders/GLTFLoader":59,"super-three/examples/js/loaders/MTLLoader":60,"super-three/examples/js/loaders/OBJLoader":61}],176:[function(_dereq_,module,exports){ var registerShader = _dereq_('../core/shader').registerShader; var THREE = _dereq_('../lib/three'); var utils = _dereq_('../utils/'); @@ -81509,14 +81755,14 @@ function getMaterialData (data, materialData) { return materialData; } -},{"../core/shader":136,"../lib/three":174,"../utils/":199}],176:[function(_dereq_,module,exports){ +},{"../core/shader":137,"../lib/three":175,"../utils/":200}],177:[function(_dereq_,module,exports){ _dereq_('./flat'); _dereq_('./standard'); _dereq_('./sdf'); _dereq_('./msdf'); _dereq_('./ios10hls'); -},{"./flat":175,"./ios10hls":177,"./msdf":178,"./sdf":179,"./standard":180}],177:[function(_dereq_,module,exports){ +},{"./flat":176,"./ios10hls":178,"./msdf":179,"./sdf":180,"./standard":181}],178:[function(_dereq_,module,exports){ var registerShader = _dereq_('../core/shader').registerShader; /** @@ -81551,7 +81797,7 @@ module.exports.Shader = registerShader('ios10hls', { }); -},{"../core/shader":136}],178:[function(_dereq_,module,exports){ +},{"../core/shader":137}],179:[function(_dereq_,module,exports){ var registerShader = _dereq_('../core/shader').registerShader; /** @@ -81627,7 +81873,7 @@ module.exports.Shader = registerShader('msdf', { ].join('\n') }); -},{"../core/shader":136}],179:[function(_dereq_,module,exports){ +},{"../core/shader":137}],180:[function(_dereq_,module,exports){ var registerShader = _dereq_('../core/shader').registerShader; /** @@ -81741,7 +81987,7 @@ module.exports.Shader = registerShader('sdf', { ].join('\n') }); -},{"../core/shader":136}],180:[function(_dereq_,module,exports){ +},{"../core/shader":137}],181:[function(_dereq_,module,exports){ var registerShader = _dereq_('../core/shader').registerShader; var THREE = _dereq_('../lib/three'); var utils = _dereq_('../utils/'); @@ -81933,11 +82179,11 @@ function getMaterialData (data, materialData) { return materialData; } -},{"../core/shader":136,"../lib/three":174,"../utils/":199}],181:[function(_dereq_,module,exports){ +},{"../core/shader":137,"../lib/three":175,"../utils/":200}],182:[function(_dereq_,module,exports){ var css = "html.a-fullscreen{bottom:0;left:0;position:fixed;right:0;top:0}html.a-fullscreen body{height:100%;margin:0;overflow:hidden;padding:0;width:100%}html.a-fullscreen .a-canvas{width:100%!important;height:100%!important;top:0!important;left:0!important;right:0!important;bottom:0!important;position:fixed!important}html:not(.a-fullscreen) .a-enter-ar,html:not(.a-fullscreen) .a-enter-vr{right:5px;bottom:5px}:-webkit-full-screen{background-color:transparent}.a-hidden{display:none!important}.a-canvas{height:100%;left:0;position:absolute;top:0;width:100%}.a-canvas.a-grab-cursor:hover{cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}canvas.a-canvas.a-mouse-cursor-hover:hover{cursor:pointer}.a-inspector-loader{background-color:#ed3160;position:fixed;left:3px;top:3px;padding:6px 10px;color:#fff;text-decoration:none;font-size:12px;font-family:Roboto,sans-serif;text-align:center;z-index:99999;width:204px}@keyframes dots-1{from{opacity:0}25%{opacity:1}}@keyframes dots-2{from{opacity:0}50%{opacity:1}}@keyframes dots-3{from{opacity:0}75%{opacity:1}}@-webkit-keyframes dots-1{from{opacity:0}25%{opacity:1}}@-webkit-keyframes dots-2{from{opacity:0}50%{opacity:1}}@-webkit-keyframes dots-3{from{opacity:0}75%{opacity:1}}.a-inspector-loader .dots span{animation:dots-1 2s infinite steps(1);-webkit-animation:dots-1 2s infinite steps(1)}.a-inspector-loader .dots span:first-child+span{animation-name:dots-2;-webkit-animation-name:dots-2}.a-inspector-loader .dots span:first-child+span+span{animation-name:dots-3;-webkit-animation-name:dots-3}a-scene{display:block;position:relative;height:100%;width:100%}a-assets,a-scene audio,a-scene img,a-scene video{display:none}.a-enter-vr-modal,.a-orientation-modal{font-family:Consolas,Andale Mono,Courier New,monospace}.a-enter-vr-modal a{border-bottom:1px solid #fff;padding:2px 0;text-decoration:none;transition:.1s color ease-in}.a-enter-vr-modal a:hover{background-color:#fff;color:#111;padding:2px 4px;position:relative;left:-4px}.a-enter-ar,.a-enter-vr{font-family:sans-serif,monospace;font-size:13px;width:100%;font-weight:200;line-height:16px;position:absolute;right:20px;bottom:20px}.a-enter-ar{right:80px}.a-enter-vr-button,.a-enter-vr-modal,.a-enter-vr-modal a{color:#fff;user-select:none;outline:0}.a-enter-vr-button{background:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='108' height='62' viewBox='0 0 108 62'%3E%3Ctitle%3Eaframe-vrmode-noborder-reduced-tracking%3C/title%3E%3Cpath d='M68.81,21.56H64.23v8.27h4.58a4.13,4.13,0,0,0,3.1-1.09,4.2,4.2,0,0,0,1-3,4.24,4.24,0,0,0-1-3A4.05,4.05,0,0,0,68.81,21.56Z' fill='%23fff'/%3E%3Cpath d='M96,0H12A12,12,0,0,0,0,12V50A12,12,0,0,0,12,62H96a12,12,0,0,0,12-12V12A12,12,0,0,0,96,0ZM41.9,46H34L24,16h8l6,21.84,6-21.84H52Zm39.29,0H73.44L68.15,35.39H64.23V46H57V16H68.81q5.32,0,8.34,2.37a8,8,0,0,1,3,6.69,9.68,9.68,0,0,1-1.27,5.18,8.9,8.9,0,0,1-4,3.34l6.26,12.11Z' fill='%23fff'/%3E%3C/svg%3E\") 50% 50% no-repeat rgba(0,0,0,.35)}.a-enter-ar-button{background:url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='108' height='62' viewBox='0 0 108 62'%3E%3Ctitle%3Eaframe-armode-noborder-reduced-tracking%3C/title%3E%3Cpath d='M96,0H12A12,12,0,0,0,0,12V50A12,12,0,0,0,12,62H96a12,12,0,0,0,12-12V12A12,12,0,0,0,96,0Zm8,50a8,8,0,0,1-8,8H12a8,8,0,0,1-8-8V12a8,8,0,0,1,8-8H96a8,8,0,0,1,8,8Z' fill='%23fff'/%3E%3Cpath d='M43.35,39.82H32.51L30.45,46H23.88L35,16h5.73L52,46H45.43Zm-9.17-5h7.5L37.91,23.58Z' fill='%23fff'/%3E%3Cpath d='M68.11,35H63.18V46H57V16H68.15q5.31,0,8.2,2.37a8.18,8.18,0,0,1,2.88,6.7,9.22,9.22,0,0,1-1.33,5.12,9.09,9.09,0,0,1-4,3.26l6.49,12.26V46H73.73Zm-4.93-5h5a5.09,5.09,0,0,0,3.6-1.18,4.21,4.21,0,0,0,1.28-3.27,4.56,4.56,0,0,0-1.2-3.34A5,5,0,0,0,68.15,21h-5Z' fill='%23fff'/%3E%3C/svg%3E\") 50% 50% no-repeat rgba(0,0,0,.2)}.a-enter-ar-button,.a-enter-vr-button{background-size:90% 90%;border:0;bottom:0;cursor:pointer;min-width:58px;min-height:34px;padding-right:0;padding-top:0;position:absolute;right:0;transition:background-color .05s ease;-webkit-transition:background-color .05s ease;z-index:9999;border-radius:8px;touch-action:manipulation}.a-enter-ar-button{background-size:100% 90%;margin-right:10px;border-radius:7px}.a-enter-ar-button:active,.a-enter-ar-button:hover,.a-enter-vr-button:active,.a-enter-vr-button:hover{background-color:#ef2d5e}.a-enter-vr-button.resethover{background-color:rgba(0,0,0,.35)}[data-a-enter-vr-no-webvr] .a-enter-vr-button{border-color:#666;opacity:.65}[data-a-enter-vr-no-webvr] .a-enter-vr-button:active,[data-a-enter-vr-no-webvr] .a-enter-vr-button:hover{background-color:rgba(0,0,0,.35);cursor:not-allowed}.a-enter-vr-modal{background-color:#666;border-radius:0;display:none;min-height:32px;margin-right:70px;padding:9px;width:280px;right:2%;position:absolute}.a-enter-vr-modal:after{border-bottom:10px solid transparent;border-left:10px solid #666;border-top:10px solid transparent;display:inline-block;content:'';position:absolute;right:-5px;top:5px;width:0;height:0}.a-enter-vr-modal a,.a-enter-vr-modal p{display:inline}.a-enter-vr-modal p{margin:0}.a-enter-vr-modal p:after{content:' '}[data-a-enter-vr-no-headset].a-enter-vr:hover .a-enter-vr-modal,[data-a-enter-vr-no-webvr].a-enter-vr:hover .a-enter-vr-modal{display:block}.a-orientation-modal{background:url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20version%3D%221.1%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%2090%2090%22%20enable-background%3D%22new%200%200%2090%2090%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%220%2C0%200%2C0%200%2C0%20%22%3E%3C/polygon%3E%3Cg%3E%3Cpath%20d%3D%22M71.545%2C48.145h-31.98V20.743c0-2.627-2.138-4.765-4.765-4.765H18.456c-2.628%2C0-4.767%2C2.138-4.767%2C4.765v42.789%20%20%20c0%2C2.628%2C2.138%2C4.766%2C4.767%2C4.766h5.535v0.959c0%2C2.628%2C2.138%2C4.765%2C4.766%2C4.765h42.788c2.628%2C0%2C4.766-2.137%2C4.766-4.765V52.914%20%20%20C76.311%2C50.284%2C74.173%2C48.145%2C71.545%2C48.145z%20M18.455%2C16.935h16.344c2.1%2C0%2C3.808%2C1.708%2C3.808%2C3.808v27.401H37.25V22.636%20%20%20c0-0.264-0.215-0.478-0.479-0.478H16.482c-0.264%2C0-0.479%2C0.214-0.479%2C0.478v36.585c0%2C0.264%2C0.215%2C0.478%2C0.479%2C0.478h7.507v7.644%20%20%20h-5.534c-2.101%2C0-3.81-1.709-3.81-3.81V20.743C14.645%2C18.643%2C16.354%2C16.935%2C18.455%2C16.935z%20M16.96%2C23.116h19.331v25.031h-7.535%20%20%20c-2.628%2C0-4.766%2C2.139-4.766%2C4.768v5.828h-7.03V23.116z%20M71.545%2C73.064H28.757c-2.101%2C0-3.81-1.708-3.81-3.808V52.914%20%20%20c0-2.102%2C1.709-3.812%2C3.81-3.812h42.788c2.1%2C0%2C3.809%2C1.71%2C3.809%2C3.812v16.343C75.354%2C71.356%2C73.645%2C73.064%2C71.545%2C73.064z%22%3E%3C/path%3E%3Cpath%20d%3D%22M28.919%2C58.424c-1.466%2C0-2.659%2C1.193-2.659%2C2.66c0%2C1.466%2C1.193%2C2.658%2C2.659%2C2.658c1.468%2C0%2C2.662-1.192%2C2.662-2.658%20%20%20C31.581%2C59.617%2C30.387%2C58.424%2C28.919%2C58.424z%20M28.919%2C62.786c-0.939%2C0-1.703-0.764-1.703-1.702c0-0.939%2C0.764-1.704%2C1.703-1.704%20%20%20c0.94%2C0%2C1.705%2C0.765%2C1.705%2C1.704C30.623%2C62.022%2C29.858%2C62.786%2C28.919%2C62.786z%22%3E%3C/path%3E%3Cpath%20d%3D%22M69.654%2C50.461H33.069c-0.264%2C0-0.479%2C0.215-0.479%2C0.479v20.288c0%2C0.264%2C0.215%2C0.478%2C0.479%2C0.478h36.585%20%20%20c0.263%2C0%2C0.477-0.214%2C0.477-0.478V50.939C70.131%2C50.676%2C69.917%2C50.461%2C69.654%2C50.461z%20M69.174%2C51.417V70.75H33.548V51.417H69.174z%22%3E%3C/path%3E%3Cpath%20d%3D%22M45.201%2C30.296c6.651%2C0%2C12.233%2C5.351%2C12.551%2C11.977l-3.033-2.638c-0.193-0.165-0.507-0.142-0.675%2C0.048%20%20%20c-0.174%2C0.198-0.153%2C0.501%2C0.045%2C0.676l3.883%2C3.375c0.09%2C0.075%2C0.198%2C0.115%2C0.312%2C0.115c0.141%2C0%2C0.273-0.061%2C0.362-0.166%20%20%20l3.371-3.877c0.173-0.2%2C0.151-0.502-0.047-0.675c-0.194-0.166-0.508-0.144-0.676%2C0.048l-2.592%2C2.979%20%20%20c-0.18-3.417-1.629-6.605-4.099-9.001c-2.538-2.461-5.877-3.817-9.404-3.817c-0.264%2C0-0.479%2C0.215-0.479%2C0.479%20%20%20C44.72%2C30.083%2C44.936%2C30.296%2C45.201%2C30.296z%22%3E%3C/path%3E%3C/g%3E%3C/svg%3E) center/50% 50% no-repeat rgba(244,244,244,1);bottom:0;font-size:14px;font-weight:600;left:0;line-height:20px;right:0;position:fixed;top:0;z-index:9999999}.a-orientation-modal:after{color:#666;content:\"Insert phone into Cardboard holder.\";display:block;position:absolute;text-align:center;top:70%;transform:translateY(-70%);width:100%}.a-orientation-modal button{background:url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20xmlns%3Axlink%3D%22http%3A//www.w3.org/1999/xlink%22%20version%3D%221.1%22%20x%3D%220px%22%20y%3D%220px%22%20viewBox%3D%220%200%20100%20100%22%20enable-background%3D%22new%200%200%20100%20100%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23000000%22%20d%3D%22M55.209%2C50l17.803-17.803c1.416-1.416%2C1.416-3.713%2C0-5.129c-1.416-1.417-3.713-1.417-5.129%2C0L50.08%2C44.872%20%20L32.278%2C27.069c-1.416-1.417-3.714-1.417-5.129%2C0c-1.417%2C1.416-1.417%2C3.713%2C0%2C5.129L44.951%2C50L27.149%2C67.803%20%20c-1.417%2C1.416-1.417%2C3.713%2C0%2C5.129c0.708%2C0.708%2C1.636%2C1.062%2C2.564%2C1.062c0.928%2C0%2C1.856-0.354%2C2.564-1.062L50.08%2C55.13l17.803%2C17.802%20%20c0.708%2C0.708%2C1.637%2C1.062%2C2.564%2C1.062s1.856-0.354%2C2.564-1.062c1.416-1.416%2C1.416-3.713%2C0-5.129L55.209%2C50z%22%3E%3C/path%3E%3C/svg%3E) no-repeat;border:none;height:50px;text-indent:-9999px;width:50px}.a-loader-title{background-color:rgba(0,0,0,.6);font-family:sans-serif,monospace;text-align:center;font-size:20px;height:50px;font-weight:300;line-height:50px;position:absolute;right:0;left:0;top:0;color:#fff}.a-modal{background:0 0/50% 50% rgba(0,0,0,.6);bottom:0;font-size:14px;font-weight:600;left:0;line-height:20px;right:0;position:fixed;top:0;z-index:9999999}.a-dialog{position:relative;left:50%;top:50%;transform:translate(-50%,-50%);z-index:199995;width:300px;height:200px;background-size:contain;background-color:#fff;font-family:sans-serif,monospace;font-size:20px;border-radius:3px;padding:6px}.a-dialog-text-container{width:100%;height:70%;align-self:flex-start;display:flex;justify-content:center;align-content:center;flex-direction:column}.a-dialog-text{display:inline-block;font-weight:400;font-size:14pt;margin:8px}.a-dialog-buttons-container{display:inline-flex;align-self:flex-end;width:100%;height:30%}.a-dialog-button{cursor:pointer;align-self:center;opacity:.9;height:80%;width:50%;font-size:12pt;margin:4px;border-radius:2px;text-align:center;border:none;display:inline-block;-webkit-transition:all .25s ease-in-out;transition:all .25s ease-in-out;box-shadow:0 1px 3px rgba(0,0,0,.1),0 1px 2px rgba(0,0,0,.2);user-select:none}.a-dialog-permission-button:hover{box-shadow:0 7px 14px rgba(0,0,0,.2),0 2px 2px rgba(0,0,0,.2)}.a-dialog-allow-button{background-color:#00ceff}.a-dialog-deny-button{background-color:#ff005b}.a-dialog-ok-button{background-color:#00ceff;width:100%}"; (_dereq_("browserify-css").createStyle(css, { "href": "src/style/aframe.css"})); module.exports = css; -},{"browserify-css":4}],182:[function(_dereq_,module,exports){ -var css = ".rs-base{background-color:#333;color:#fafafa;border-radius:0;font:10px monospace;left:5px;line-height:1em;opacity:.85;overflow:hidden;padding:10px;position:fixed;top:5px;width:300px;z-index:10000}.rs-base div.hidden{display:none}.rs-base h1{color:#fff;cursor:pointer;font-size:1.4em;font-weight:300;margin:0 0 5px;padding:0}.rs-group{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-direction:column-reverse;flex-direction:column-reverse;margin-bottom:5px}.rs-group:last-child{margin-bottom:0}.rs-counter-base{align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;height:10px;-webkit-justify-content:space-between;justify-content:space-between;margin:2px 0}.rs-counter-base.alarm{color:#b70000;text-shadow:0 0 0 #b70000,0 0 1px #fff,0 0 1px #fff,0 0 2px #fff,0 0 2px #fff,0 0 3px #fff,0 0 3px #fff,0 0 4px #fff,0 0 4px #fff}.rs-counter-id{font-weight:300;-webkit-box-ordinal-group:0;-webkit-order:0;order:0;width:54px}.rs-counter-value{font-weight:300;-webkit-box-ordinal-group:1;-webkit-order:1;order:1;text-align:right;width:35px}.rs-canvas{-webkit-box-ordinal-group:2;-webkit-order:2;order:2}@media (min-width:480px){.rs-base{left:20px;top:20px}}"; (_dereq_("browserify-css").createStyle(css, { "href": "src/style/rStats.css"})); module.exports = css; },{"browserify-css":4}],183:[function(_dereq_,module,exports){ +var css = ".rs-base{background-color:#333;color:#fafafa;border-radius:0;font:10px monospace;left:5px;line-height:1em;opacity:.85;overflow:hidden;padding:10px;position:fixed;top:5px;width:300px;z-index:10000}.rs-base div.hidden{display:none}.rs-base h1{color:#fff;cursor:pointer;font-size:1.4em;font-weight:300;margin:0 0 5px;padding:0}.rs-group{display:-webkit-box;display:-webkit-flex;display:flex;-webkit-flex-direction:column-reverse;flex-direction:column-reverse;margin-bottom:5px}.rs-group:last-child{margin-bottom:0}.rs-counter-base{align-items:center;display:-webkit-box;display:-webkit-flex;display:flex;height:10px;-webkit-justify-content:space-between;justify-content:space-between;margin:2px 0}.rs-counter-base.alarm{color:#b70000;text-shadow:0 0 0 #b70000,0 0 1px #fff,0 0 1px #fff,0 0 2px #fff,0 0 2px #fff,0 0 3px #fff,0 0 3px #fff,0 0 4px #fff,0 0 4px #fff}.rs-counter-id{font-weight:300;-webkit-box-ordinal-group:0;-webkit-order:0;order:0;width:54px}.rs-counter-value{font-weight:300;-webkit-box-ordinal-group:1;-webkit-order:1;order:1;text-align:right;width:35px}.rs-canvas{-webkit-box-ordinal-group:2;-webkit-order:2;order:2}@media (min-width:480px){.rs-base{left:20px;top:20px}}"; (_dereq_("browserify-css").createStyle(css, { "href": "src/style/rStats.css"})); module.exports = css; +},{"browserify-css":4}],184:[function(_dereq_,module,exports){ var constants = _dereq_('../constants/'); var registerSystem = _dereq_('../core/system').registerSystem; @@ -82210,7 +82456,7 @@ function removeDefaultCamera (sceneEl) { sceneEl.removeChild(defaultCamera); } -},{"../constants/":118,"../core/system":137}],184:[function(_dereq_,module,exports){ +},{"../constants/":119,"../core/system":138}],185:[function(_dereq_,module,exports){ var geometries = _dereq_('../core/geometry').geometries; var registerSystem = _dereq_('../core/system').registerSystem; var THREE = _dereq_('../lib/three'); @@ -82350,7 +82596,7 @@ function toBufferGeometry (geometry, doBuffer) { return bufferGeometry; } -},{"../core/geometry":127,"../core/system":137,"../lib/three":174}],185:[function(_dereq_,module,exports){ +},{"../core/geometry":128,"../core/system":138,"../lib/three":175}],186:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var THREE = _dereq_('../lib/three'); @@ -82386,7 +82632,7 @@ module.exports.System = registerSystem('gltf-model', { } }); -},{"../core/system":137,"../lib/three":174}],186:[function(_dereq_,module,exports){ +},{"../core/system":138,"../lib/three":175}],187:[function(_dereq_,module,exports){ _dereq_('./camera'); _dereq_('./geometry'); _dereq_('./gltf-model'); @@ -82397,7 +82643,7 @@ _dereq_('./shadow'); _dereq_('./tracked-controls-webvr'); _dereq_('./tracked-controls-webxr'); -},{"./camera":183,"./geometry":184,"./gltf-model":185,"./light":187,"./material":188,"./renderer":189,"./shadow":190,"./tracked-controls-webvr":191,"./tracked-controls-webxr":192}],187:[function(_dereq_,module,exports){ +},{"./camera":184,"./geometry":185,"./gltf-model":186,"./light":188,"./material":189,"./renderer":190,"./shadow":191,"./tracked-controls-webvr":192,"./tracked-controls-webxr":193}],188:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var bind = _dereq_('../utils/bind'); var constants = _dereq_('../constants/'); @@ -82483,7 +82729,7 @@ module.exports.System = registerSystem('light', { } }); -},{"../constants/":118,"../core/system":137,"../utils/bind":193}],188:[function(_dereq_,module,exports){ +},{"../constants/":119,"../core/system":138,"../utils/bind":194}],189:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var THREE = _dereq_('../lib/three'); var utils = _dereq_('../utils/'); @@ -82888,7 +83134,7 @@ function fixVideoAttributes (videoEl) { return videoEl; } -},{"../core/system":137,"../lib/three":174,"../utils/":199,"../utils/material":202}],189:[function(_dereq_,module,exports){ +},{"../core/system":138,"../lib/three":175,"../utils/":200,"../utils/material":203}],190:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var utils = _dereq_('../utils/'); var THREE = _dereq_('../lib/three'); @@ -82952,7 +83198,7 @@ module.exports.System = registerSystem('renderer', { } }); -},{"../core/system":137,"../lib/three":174,"../utils/":199}],190:[function(_dereq_,module,exports){ +},{"../core/system":138,"../lib/three":175,"../utils/":200}],191:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var THREE = _dereq_('../lib/three'); @@ -83007,7 +83253,7 @@ module.exports.System = registerSystem('shadow', { } }); -},{"../core/system":137,"../lib/three":174}],191:[function(_dereq_,module,exports){ +},{"../core/system":138,"../lib/three":175}],192:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var utils = _dereq_('../utils'); var isWebXRAvailable = utils.device.isWebXRAvailable; @@ -83075,7 +83321,7 @@ module.exports.System = registerSystem('tracked-controls-webvr', { } }); -},{"../core/system":137,"../utils":199}],192:[function(_dereq_,module,exports){ +},{"../core/system":138,"../utils":200}],193:[function(_dereq_,module,exports){ var registerSystem = _dereq_('../core/system').registerSystem; var utils = _dereq_('../utils'); @@ -83088,27 +83334,51 @@ module.exports.System = registerSystem('tracked-controls-webxr', { this.controllers = []; this.oldControllersLength = 0; this.throttledUpdateControllerList = utils.throttle(this.updateControllerList, 500, this); + this.updateReferenceSpace = this.updateReferenceSpace.bind(this); + this.el.addEventListener('enter-vr', this.updateReferenceSpace); + this.el.addEventListener('exit-vr', this.updateReferenceSpace); }, tick: function () { this.throttledUpdateControllerList(); }, - updateControllerList: function () { - var xrSession = this.el.xrSession; + updateReferenceSpace: function () { var self = this; - if (!xrSession) { return; } - this.controllers = this.el.xrSession.inputSources; - if (this.oldControllersLength === this.controllers.length) { return; } - this.oldControllersLength = this.controllers.length; + var xrSession = this.el.xrSession; + if (!xrSession) { + this.referenceSpace = undefined; + this.controllers = []; + if (this.oldControllersLength > 0) { + this.oldControllersLength = 0; + this.el.emit('controllersupdated', undefined, false); + } + return; + } xrSession.requestReferenceSpace('local-floor').then(function (referenceSpace) { self.referenceSpace = referenceSpace; }); + }, + + updateControllerList: function () { + var xrSession = this.el.xrSession; + if (!xrSession) { + if (this.oldControllersLength === 0) { return; } + // Broadcast that we now have zero controllers connected if there is + // no session + this.oldControllersLength = 0; + this.controllers = []; + this.el.emit('controllersupdated', undefined, false); + return; + } + this.controllers = xrSession.inputSources; + if (this.oldControllersLength === this.controllers.length) { return; } + this.oldControllersLength = this.controllers.length; this.el.emit('controllersupdated', undefined, false); } }); -},{"../core/system":137,"../utils":199}],193:[function(_dereq_,module,exports){ +},{"../core/system":138,"../utils":200}],194:[function(_dereq_,module,exports){ /** * Faster version of Function.prototype.bind * @param {Function} fn - Function to wrap. @@ -83125,7 +83395,7 @@ module.exports = function bind (fn, ctx/* , arg1, arg2 */) { })(Array.prototype.slice.call(arguments, 2)); }; -},{}],194:[function(_dereq_,module,exports){ +},{}],195:[function(_dereq_,module,exports){ /* global THREE */ var debug = _dereq_('./debug'); var extend = _dereq_('object-assign'); @@ -83237,7 +83507,7 @@ module.exports.toVector3 = function (vec3) { return new THREE.Vector3(vec3.x, vec3.y, vec3.z); }; -},{"./debug":195,"object-assign":39}],195:[function(_dereq_,module,exports){ +},{"./debug":196,"object-assign":39}],196:[function(_dereq_,module,exports){ (function (process){ var debugLib = _dereq_('debug'); var extend = _dereq_('object-assign'); @@ -83334,7 +83604,7 @@ module.exports = debug; }).call(this,_dereq_('_process')) -},{"_process":49,"debug":8,"object-assign":39}],196:[function(_dereq_,module,exports){ +},{"_process":49,"debug":8,"object-assign":39}],197:[function(_dereq_,module,exports){ (function (process){ var error = _dereq_('debug')('device:error'); @@ -83527,7 +83797,7 @@ module.exports.isNodeEnvironment = !module.exports.isBrowserEnvironment; }).call(this,_dereq_('_process')) -},{"_process":49,"debug":8}],197:[function(_dereq_,module,exports){ +},{"_process":49,"debug":8}],198:[function(_dereq_,module,exports){ /** * Split a delimited component property string (e.g., `material.color`) to an object * containing `component` name and `property` name. If there is no delimiter, just return the @@ -83589,7 +83859,7 @@ module.exports.setComponentProperty = function (el, name, value, delimiter) { el.setAttribute(name, value); }; -},{}],198:[function(_dereq_,module,exports){ +},{}],199:[function(_dereq_,module,exports){ module.exports = function forceCanvasResizeSafariMobile (canvasEl) { var width = canvasEl.style.width; var height = canvasEl.style.height; @@ -83605,7 +83875,7 @@ module.exports = function forceCanvasResizeSafariMobile (canvasEl) { }, 200); }; -},{}],199:[function(_dereq_,module,exports){ +},{}],200:[function(_dereq_,module,exports){ /* global location */ /* Centralized place to reference utilities since utils is exposed to the user. */ @@ -83935,7 +84205,7 @@ module.exports.findAllScenes = function (el) { // Must be at bottom to avoid circular dependency. module.exports.srcLoader = _dereq_('./src-loader'); -},{"./bind":193,"./coordinates":194,"./debug":195,"./device":196,"./entity":197,"./forceCanvasResizeSafariMobile":198,"./is-ie11":200,"./material":202,"./object-pool":203,"./split":204,"./src-loader":205,"./styleParser":206,"./tracked-controls":207,"deep-assign":10,"object-assign":39}],200:[function(_dereq_,module,exports){ +},{"./bind":194,"./coordinates":195,"./debug":196,"./device":197,"./entity":198,"./forceCanvasResizeSafariMobile":199,"./is-ie11":201,"./material":203,"./object-pool":204,"./split":205,"./src-loader":206,"./styleParser":207,"./tracked-controls":208,"deep-assign":10,"object-assign":39}],201:[function(_dereq_,module,exports){ // https://stackoverflow.com/a/17907562 function getInternetExplorerVersion () { var version = -1; @@ -83953,7 +84223,7 @@ function getInternetExplorerVersion () { module.exports = getInternetExplorerVersion() === 11; -},{}],201:[function(_dereq_,module,exports){ +},{}],202:[function(_dereq_,module,exports){ /** * Check if device is iOS and older than version 10. */ @@ -83961,7 +84231,7 @@ module.exports = function isIOSOlderThan10 (userAgent) { return /(iphone|ipod|ipad).*os.(7_|8_|9_)/i.test(userAgent); }; -},{}],202:[function(_dereq_,module,exports){ +},{}],203:[function(_dereq_,module,exports){ var THREE = _dereq_('../lib/three'); var HLS_MIMETYPES = ['application/x-mpegurl', 'application/vnd.apple.mpegurl']; @@ -84132,7 +84402,7 @@ module.exports.isHLS = function (src, type) { return false; }; -},{"../lib/three":174}],203:[function(_dereq_,module,exports){ +},{"../lib/three":175}],204:[function(_dereq_,module,exports){ /* Adapted deePool by Kyle Simpson. MIT License: http://getify.mit-license.org @@ -84223,7 +84493,7 @@ function removeUnusedKeys (obj, schema) { } module.exports.removeUnusedKeys = removeUnusedKeys; -},{}],204:[function(_dereq_,module,exports){ +},{}],205:[function(_dereq_,module,exports){ /** * String split with cached result. */ @@ -84240,7 +84510,7 @@ module.exports.split = (function () { }; })(); -},{}],205:[function(_dereq_,module,exports){ +},{}],206:[function(_dereq_,module,exports){ /* global Image, XMLHttpRequest */ var debug = _dereq_('./debug'); @@ -84399,7 +84669,7 @@ module.exports = { validateCubemapSrc: validateCubemapSrc }; -},{"./debug":195}],206:[function(_dereq_,module,exports){ +},{"./debug":196}],207:[function(_dereq_,module,exports){ /** * Utils for parsing style-like strings (e.g., "primitive: box; width: 5; height: 4.5"). * Some code adapted from `style-attr` (https://github.com/joshwnj/style-attr) @@ -84552,7 +84822,7 @@ function styleStringify (obj) { function upperCase (str) { return str[1].toUpperCase(); } -},{}],207:[function(_dereq_,module,exports){ +},{}],208:[function(_dereq_,module,exports){ var DEFAULT_HANDEDNESS = _dereq_('../constants').DEFAULT_HANDEDNESS; var AXIS_LABELS = ['x', 'y', 'z', 'w']; var NUM_HANDS = 2; // Number of hands in a pair. Should always be 2. @@ -84791,7 +85061,7 @@ module.exports.onButtonEvent = function (id, evtName, component, hand) { } }; -},{"../constants":118}],208:[function(_dereq_,module,exports){ +},{"../constants":119}],209:[function(_dereq_,module,exports){ /** * @author richt / http://richt.me * @author WestLangley / http://github.com/WestLangley @@ -84904,7 +85174,7 @@ THREE.DeviceOrientationControls = function ( object ) { }; -},{}],209:[function(_dereq_,module,exports){ +},{}],210:[function(_dereq_,module,exports){ window.glStats = function () { var _rS = null; @@ -85165,7 +85435,7 @@ if (typeof module === 'object') { }; } -},{}],210:[function(_dereq_,module,exports){ +},{}],211:[function(_dereq_,module,exports){ // performance.now() polyfill from https://gist.github.com/paulirish/5438650 'use strict'; @@ -85620,7 +85890,7 @@ if (typeof module === 'object') { module.exports = window.rStats; } -},{}],211:[function(_dereq_,module,exports){ +},{}],212:[function(_dereq_,module,exports){ // https://stackoverflow.com/a/36213464 if (!String.prototype.startsWith) { String.prototype.startsWith = function(searchString, position){ @@ -85629,7 +85899,7 @@ if (!String.prototype.startsWith) { }; } -},{}],212:[function(_dereq_,module,exports){ +},{}],213:[function(_dereq_,module,exports){ /* * Copyright 2015 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -85691,7 +85961,7 @@ Util.isLandscapeMode = function() { module.exports = Util; -},{}],213:[function(_dereq_,module,exports){ +},{}],214:[function(_dereq_,module,exports){ /* * Copyright 2015 Google Inc. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -85767,6 +86037,6 @@ function getWakeLock() { module.exports = getWakeLock(); -},{"./util.js":212}]},{},[172])(172) +},{"./util.js":213}]},{},[173])(173) }); //# sourceMappingURL=aframe-master.js.map diff --git a/dist/aframe-master.js.map b/dist/aframe-master.js.map index bf9ec188737..e0488fe53ba 100644 --- a/dist/aframe-master.js.map +++ b/dist/aframe-master.js.map @@ -89,6 +89,7 @@ "src/components/line.js", "src/components/link.js", "src/components/look-controls.js", + "src/components/magicleap-controls.js", "src/components/material.js", "src/components/obj-model.js", "src/components/oculus-go-controls.js", @@ -217,7 +218,7 @@ "vendor/wakelock/wakelock.js" ], "names": [], - "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7vDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACbA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACjGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACj+iDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnsGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5xBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC/4GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5mBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7YA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3dA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACneA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACneA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACp6BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnyBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACh4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/BA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5JA;AACA;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9LA;;ACAA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC5LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", + "mappings": "AAAA;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACXA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC7vDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjDA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7CA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACbA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC1SA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;ACjGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC/BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC5BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACxLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AClMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACr/iDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3nBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnsGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnhBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5xBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC3EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC/4GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5mBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpaA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/RA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClXA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5dA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACvEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACnHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACneA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9PA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpeA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtRA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACp6BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnyBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/NA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACj4BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/BA;AACA;AACA;AACA;AACA;;ACJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1MA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5JA;AACA;;ACDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/CA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrMA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;;ACHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3BA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACtBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACbA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC3HA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpEA;AACA;AACA;AACA;AACA;AACA;;ACLA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACjCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1EA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChHA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9LA;;ACAA;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/QA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC1IA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClCA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACpFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnZA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC9DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AClEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvDA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;AC5FA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC5LA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACdA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACxUA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AChBA;AACA;AACA;AACA;AACA;AACA;AACA;;ACNA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzKA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACzFA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACfA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7JA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACvJA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC7OA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC/GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACnQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACrcA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;ACPA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AC5DA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "file": "generated.js", "sourceRoot": "", "sourcesContent": [ @@ -278,7 +279,7 @@ "'use strict';\n\nvar implementation = require('./implementation');\n\nvar zeroWidthSpace = '\\u200b';\n\nmodule.exports = function getPolyfill() {\n\tif (String.prototype.trim && zeroWidthSpace.trim() === zeroWidthSpace) {\n\t\treturn String.prototype.trim;\n\t}\n\treturn implementation;\n};\n", "'use strict';\n\nvar define = require('define-properties');\nvar getPolyfill = require('./polyfill');\n\nmodule.exports = function shimStringTrim() {\n\tvar polyfill = getPolyfill();\n\tdefine(String.prototype, { trim: polyfill }, {\n\t\ttrim: function testTrim() {\n\t\t\treturn String.prototype.trim !== polyfill;\n\t\t}\n\t});\n\treturn polyfill;\n};\n", "/*\n * anime.js v3.0.0\n * (c) 2019 Julian Garnier\n * Released under the MIT license\n * animejs.com\n */\n\n'use strict';\n\n// Defaults\n\nvar defaultInstanceSettings = {\n update: null,\n begin: null,\n loopBegin: null,\n changeBegin: null,\n change: null,\n changeComplete: null,\n loopComplete: null,\n complete: null,\n loop: 1,\n direction: 'normal',\n autoplay: true,\n timelineOffset: 0\n};\n\nvar defaultTweenSettings = {\n duration: 1000,\n delay: 0,\n endDelay: 0,\n easing: 'easeOutElastic(1, .5)',\n round: 0\n};\n\nvar validTransforms = ['translateX', 'translateY', 'translateZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'perspective'];\n\n// Caching\n\nvar cache = {\n CSS: {},\n springs: {}\n};\n\n// Utils\n\nfunction minMax(val, min, max) {\n return Math.min(Math.max(val, min), max);\n}\n\nfunction stringContains(str, text) {\n return str.indexOf(text) > -1;\n}\n\nfunction applyArguments(func, args) {\n return func.apply(null, args);\n}\n\nvar hexRegex = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i;\nvar rgbPrefixRegex = /^rgb/;\nvar hslRegex = /^hsl/;\n\nvar is = {\n arr: function (a) { return Array.isArray(a); },\n obj: function (a) { return stringContains(Object.prototype.toString.call(a), 'Object'); },\n pth: function (a) { return is.obj(a) && a.hasOwnProperty('totalLength'); },\n svg: function (a) { return a instanceof SVGElement; },\n inp: function (a) { return a instanceof HTMLInputElement; },\n dom: function (a) { return a.nodeType || is.svg(a); },\n str: function (a) { return typeof a === 'string'; },\n fnc: function (a) { return typeof a === 'function'; },\n und: function (a) { return typeof a === 'undefined'; },\n hex: function (a) { return hexRegex.test(a); },\n rgb: function (a) { return rgbPrefixRegex.test(a); },\n hsl: function (a) { return hslRegex.test(a); },\n col: function (a) { return (is.hex(a) || is.rgb(a) || is.hsl(a)); },\n key: function (a) { return !defaultInstanceSettings.hasOwnProperty(a) && !defaultTweenSettings.hasOwnProperty(a) && a !== 'targets' && a !== 'keyframes'; }\n};\n\n// Easings\n\nvar easingFunctionRegex = /\\(([^)]+)\\)/;\n\nfunction parseEasingParameters(string) {\n var match = easingFunctionRegex.exec(string);\n return match ? match[1].split(',').map(function (p) { return parseFloat(p); }) : [];\n}\n\n// Spring solver inspired by Webkit Copyright © 2016 Apple Inc. All rights reserved. https://webkit.org/demos/spring/spring.js\n\nfunction spring(string, duration) {\n\n var params = parseEasingParameters(string);\n var mass = minMax(is.und(params[0]) ? 1 : params[0], .1, 100);\n var stiffness = minMax(is.und(params[1]) ? 100 : params[1], .1, 100);\n var damping = minMax(is.und(params[2]) ? 10 : params[2], .1, 100);\n var velocity = minMax(is.und(params[3]) ? 0 : params[3], .1, 100);\n var w0 = Math.sqrt(stiffness / mass);\n var zeta = damping / (2 * Math.sqrt(stiffness * mass));\n var wd = zeta < 1 ? w0 * Math.sqrt(1 - zeta * zeta) : 0;\n var a = 1;\n var b = zeta < 1 ? (zeta * w0 + -velocity) / wd : -velocity + w0;\n\n function solver(t) {\n var progress = duration ? (duration * t) / 1000 : t;\n if (zeta < 1) {\n progress = Math.exp(-progress * zeta * w0) * (a * Math.cos(wd * progress) + b * Math.sin(wd * progress));\n } else {\n progress = (a + b * progress) * Math.exp(-progress * w0);\n }\n if (t === 0 || t === 1) { return t; }\n return 1 - progress;\n }\n\n function getDuration() {\n var cached = cache.springs[string];\n if (cached) { return cached; }\n var frame = 1/6;\n var elapsed = 0;\n var rest = 0;\n while(true) {\n elapsed += frame;\n if (solver(elapsed) === 1) {\n rest++;\n if (rest >= 16) { break; }\n } else {\n rest = 0;\n }\n }\n var duration = elapsed * frame * 1000;\n cache.springs[string] = duration;\n return duration;\n }\n\n return duration ? solver : getDuration;\n\n}\n\n// Elastic easing adapted from jQueryUI http://api.jqueryui.com/easings/\n\nfunction elastic(amplitude, period) {\n if ( amplitude === void 0 ) amplitude = 1;\n if ( period === void 0 ) period = .5;\n\n var a = minMax(amplitude, 1, 10);\n var p = minMax(period, .1, 2);\n return function (t) {\n return (t === 0 || t === 1) ? t :\n -a * Math.pow(2, 10 * (t - 1)) * Math.sin((((t - 1) - (p / (Math.PI * 2) * Math.asin(1 / a))) * (Math.PI * 2)) / p);\n }\n}\n\n// Basic steps easing implementation https://developer.mozilla.org/fr/docs/Web/CSS/transition-timing-function\n\nfunction steps(steps) {\n if ( steps === void 0 ) steps = 10;\n\n return function (t) { return Math.round(t * steps) * (1 / steps); };\n}\n\n// BezierEasing https://github.com/gre/bezier-easing\n\nvar bezier = (function () {\n\n var kSplineTableSize = 11;\n var kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\n function A(aA1, aA2) { return 1.0 - 3.0 * aA2 + 3.0 * aA1 }\n function B(aA1, aA2) { return 3.0 * aA2 - 6.0 * aA1 }\n function C(aA1) { return 3.0 * aA1 }\n\n function calcBezier(aT, aA1, aA2) { return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT }\n function getSlope(aT, aA1, aA2) { return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1) }\n\n function binarySubdivide(aX, aA, aB, mX1, mX2) {\n var currentX, currentT, i = 0;\n do {\n currentT = aA + (aB - aA) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) { aB = currentT; } else { aA = currentT; }\n } while (Math.abs(currentX) > 0.0000001 && ++i < 10);\n return currentT;\n }\n\n function newtonRaphsonIterate(aX, aGuessT, mX1, mX2) {\n for (var i = 0; i < 4; ++i) {\n var currentSlope = getSlope(aGuessT, mX1, mX2);\n if (currentSlope === 0.0) { return aGuessT; }\n var currentX = calcBezier(aGuessT, mX1, mX2) - aX;\n aGuessT -= currentX / currentSlope;\n }\n return aGuessT;\n }\n\n function bezier(mX1, mY1, mX2, mY2) {\n\n if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) { return; }\n var sampleValues = new Float32Array(kSplineTableSize);\n\n if (mX1 !== mY1 || mX2 !== mY2) {\n for (var i = 0; i < kSplineTableSize; ++i) {\n sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);\n }\n }\n\n function getTForX(aX) {\n\n var intervalStart = 0;\n var currentSample = 1;\n var lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n\n --currentSample;\n\n var dist = (aX - sampleValues[currentSample]) / (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n var guessForT = intervalStart + dist * kSampleStepSize;\n var initialSlope = getSlope(guessForT, mX1, mX2);\n\n if (initialSlope >= 0.001) {\n return newtonRaphsonIterate(aX, guessForT, mX1, mX2);\n } else if (initialSlope === 0.0) {\n return guessForT;\n } else {\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);\n }\n\n }\n\n return function (x) {\n if (mX1 === mY1 && mX2 === mY2) { return x; }\n if (x === 0 || x === 1) { return x; }\n return calcBezier(getTForX(x), mY1, mY2);\n }\n\n }\n\n return bezier;\n\n})();\n\nvar penner = (function () {\n\n var names = ['Quad', 'Cubic', 'Quart', 'Quint', 'Sine', 'Expo', 'Circ', 'Back', 'Elastic'];\n\n // Approximated Penner equations http://matthewlein.com/ceaser/\n\n var curves = {\n In: [\n [0.550, 0.085, 0.680, 0.530], /* inQuad */\n [0.550, 0.055, 0.675, 0.190], /* inCubic */\n [0.895, 0.030, 0.685, 0.220], /* inQuart */\n [0.755, 0.050, 0.855, 0.060], /* inQuint */\n [0.470, 0.000, 0.745, 0.715], /* inSine */\n [0.950, 0.050, 0.795, 0.035], /* inExpo */\n [0.600, 0.040, 0.980, 0.335], /* inCirc */\n [0.600,-0.280, 0.735, 0.045], /* inBack */\n elastic /* inElastic */\n ],\n Out: [\n [0.250, 0.460, 0.450, 0.940], /* outQuad */\n [0.215, 0.610, 0.355, 1.000], /* outCubic */\n [0.165, 0.840, 0.440, 1.000], /* outQuart */\n [0.230, 1.000, 0.320, 1.000], /* outQuint */\n [0.390, 0.575, 0.565, 1.000], /* outSine */\n [0.190, 1.000, 0.220, 1.000], /* outExpo */\n [0.075, 0.820, 0.165, 1.000], /* outCirc */\n [0.175, 0.885, 0.320, 1.275], /* outBack */\n function (a, p) { return function (t) { return 1 - elastic(a, p)(1 - t); }; } /* outElastic */\n ],\n InOut: [\n [0.455, 0.030, 0.515, 0.955], /* inOutQuad */\n [0.645, 0.045, 0.355, 1.000], /* inOutCubic */\n [0.770, 0.000, 0.175, 1.000], /* inOutQuart */\n [0.860, 0.000, 0.070, 1.000], /* inOutQuint */\n [0.445, 0.050, 0.550, 0.950], /* inOutSine */\n [1.000, 0.000, 0.000, 1.000], /* inOutExpo */\n [0.785, 0.135, 0.150, 0.860], /* inOutCirc */\n [0.680,-0.550, 0.265, 1.550], /* inOutBack */\n function (a, p) { return function (t) { return t < .5 ? elastic(a, p)(t * 2) / 2 : 1 - elastic(a, p)(t * -2 + 2) / 2; }; } /* inOutElastic */\n ]\n };\n\n var eases = {\n linear: [0.250, 0.250, 0.750, 0.750]\n };\n\n for (var coords in curves) {\n for (var i = 0, len = curves[coords].length; i < len; i++) {\n eases['ease'+coords+names[i]] = curves[coords][i];\n }\n }\n\n return eases;\n\n})();\n\nfunction parseEasings(easing, duration) {\n if (is.fnc(easing)) { return easing; }\n var name = easing.split('(')[0];\n var ease = penner[name];\n var args = parseEasingParameters(easing);\n switch (name) {\n case 'spring' : return spring(easing, duration);\n case 'cubicBezier' : return applyArguments(bezier, args);\n case 'steps' : return applyArguments(steps, args);\n default : return is.fnc(ease) ? applyArguments(ease, args) : applyArguments(bezier, ease);\n }\n}\n\n// Strings\n\nfunction selectString(str) {\n try {\n var nodes = document.querySelectorAll(str);\n return nodes;\n } catch(e) {\n return;\n }\n}\n\n// Arrays\n\nvar auxArrayFilter = [];\n\nfunction filterArray(arr, callback) {\n var result = auxArrayFilter;\n\n var len = arr.length;\n var thisArg = arguments.length >= 2 ? arguments[1] : void 0;\n for (var i = 0; i < len; i++) {\n if (i in arr) {\n var val = arr[i];\n if (callback.call(thisArg, val, i, arr)) {\n result.push(val);\n }\n }\n }\n\n // arr turns into the auxArray and we return the previously aux array.\n auxArrayFilter = arr;\n auxArrayFilter.length = 0;\n return result;\n}\n\nfunction flattenArray (arr, result) {\n if (!result) { result = []; }\n for (var i = 0, length = arr.length; i < length; i++) {\n var value = arr[i];\n if (Array.isArray(value)) {\n flattenArray(value, result);\n } else {\n result.push(value);\n }\n }\n return result;\n}\n\nfunction toArray(o) {\n if (is.arr(o)) { return o; }\n if (is.str(o)) { o = selectString(o) || o; }\n if (o instanceof NodeList || o instanceof HTMLCollection) { return [].slice.call(o); }\n return [o];\n}\n\nfunction arrayContains(arr, val) {\n return arr.some(function (a) { return a === val; });\n}\n\n// Objects\n\nfunction cloneObject(o) {\n var clone = {};\n for (var p in o) { clone[p] = o[p]; }\n return clone;\n}\n\nfunction replaceObjectProps(o1, o2) {\n var o = cloneObject(o1);\n for (var p in o1) { o[p] = o2.hasOwnProperty(p) ? o2[p] : o1[p]; }\n return o;\n}\n\nfunction mergeObjects(o1, o2) {\n var o = cloneObject(o1);\n for (var p in o2) { o[p] = is.und(o1[p]) ? o2[p] : o1[p]; }\n return o;\n}\n\n// Colors\n\nvar rgbRegex = /rgb\\((\\d+,\\s*[\\d]+,\\s*[\\d]+)\\)/g;\n\nfunction rgbToRgba(rgbValue) {\n var rgb = rgbRegex.exec(rgbValue);\n return rgb ? (\"rgba(\" + (rgb[1]) + \",1)\") : rgbValue;\n}\n\nvar hexToRgbaHexRegex = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\nvar hexToRgbaRgbRegex = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i;\n\nfunction hexToRgba(hexValue) {\n var hex = hexValue.replace(hexToRgbaHexRegex, function (m, r, g, b) { return r + r + g + g + b + b; } );\n var rgb = hexToRgbaRgbRegex.exec(hex);\n var r = parseInt(rgb[1], 16);\n var g = parseInt(rgb[2], 16);\n var b = parseInt(rgb[3], 16);\n return (\"rgba(\" + r + \",\" + g + \",\" + b + \",1)\");\n}\n\nvar hslToRgbaHsl1Regex = /hsl\\((\\d+),\\s*([\\d.]+)%,\\s*([\\d.]+)%\\)/g;\nvar hslToRgbaHsl2Regex = /hsla\\((\\d+),\\s*([\\d.]+)%,\\s*([\\d.]+)%,\\s*([\\d.]+)\\)/g;\n\nfunction hslToRgba(hslValue) {\n var hsl = hslToRgbaHsl1Regex.exec(hslValue) || hslToRgbaHsl2Regex.exec(hslValue);\n var h = parseInt(hsl[1], 10) / 360;\n var s = parseInt(hsl[2], 10) / 100;\n var l = parseInt(hsl[3], 10) / 100;\n var a = hsl[4] || 1;\n function hue2rgb(p, q, t) {\n if (t < 0) { t += 1; }\n if (t > 1) { t -= 1; }\n if (t < 1/6) { return p + (q - p) * 6 * t; }\n if (t < 1/2) { return q; }\n if (t < 2/3) { return p + (q - p) * (2/3 - t) * 6; }\n return p;\n }\n var r, g, b;\n if (s == 0) {\n r = g = b = l;\n } else {\n var q = l < 0.5 ? l * (1 + s) : l + s - l * s;\n var p = 2 * l - q;\n r = hue2rgb(p, q, h + 1/3);\n g = hue2rgb(p, q, h);\n b = hue2rgb(p, q, h - 1/3);\n }\n return (\"rgba(\" + (r * 255) + \",\" + (g * 255) + \",\" + (b * 255) + \",\" + a + \")\");\n}\n\nfunction colorToRgb(val) {\n if (is.rgb(val)) { return rgbToRgba(val); }\n if (is.hex(val)) { return hexToRgba(val); }\n if (is.hsl(val)) { return hslToRgba(val); }\n}\n\n// Units\n\nvar unitRegex = /([\\+\\-]?[0-9#\\.]+)(%|px|pt|em|rem|in|cm|mm|ex|ch|pc|vw|vh|vmin|vmax|deg|rad|turn)?$/;\n\nfunction getUnit(val) {\n var split = unitRegex.exec(val);\n if (split) { return split[2]; }\n}\n\nfunction getTransformUnit(propName) {\n if (stringContains(propName, 'translate') || propName === 'perspective') { return 'px'; }\n if (stringContains(propName, 'rotate') || stringContains(propName, 'skew')) { return 'deg'; }\n}\n\n// Values\n\nfunction getFunctionValue(val, animatable) {\n if (!is.fnc(val)) { return val; }\n return val(animatable.target, animatable.id, animatable.total);\n}\n\nfunction getAttribute(el, prop) {\n return el.getAttribute(prop);\n}\n\nfunction convertPxToUnit(el, value, unit) {\n var valueUnit = getUnit(value);\n if (arrayContains([unit, 'deg', 'rad', 'turn'], valueUnit)) { return value; }\n var cached = cache.CSS[value + unit];\n if (!is.und(cached)) { return cached; }\n var baseline = 100;\n var tempEl = document.createElement(el.tagName);\n var parentEl = (el.parentNode && (el.parentNode !== document)) ? el.parentNode : document.body;\n parentEl.appendChild(tempEl);\n tempEl.style.position = 'absolute';\n tempEl.style.width = baseline + unit;\n var factor = baseline / tempEl.offsetWidth;\n parentEl.removeChild(tempEl);\n var convertedUnit = factor * parseFloat(value);\n cache.CSS[value + unit] = convertedUnit;\n return convertedUnit;\n}\n\nfunction getCSSValue(el, prop, unit) {\n if (prop in el.style) {\n var uppercasePropName = prop.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();\n var value = el.style[prop] || getComputedStyle(el).getPropertyValue(uppercasePropName) || '0';\n return unit ? convertPxToUnit(el, value, unit) : value;\n }\n}\n\nfunction getAnimationType(el, prop) {\n if (is.dom(el) && !is.inp(el) && (getAttribute(el, prop) || (is.svg(el) && el[prop]))) { return 'attribute'; }\n if (is.dom(el) && arrayContains(validTransforms, prop)) { return 'transform'; }\n if (is.dom(el) && (prop !== 'transform' && getCSSValue(el, prop))) { return 'css'; }\n if (el[prop] != null) { return 'object'; }\n}\n\nvar transformRegex = /(\\w+)\\(([^)]*)\\)/g;\n\nfunction getElementTransforms(el) {\n if (!is.dom(el)) { return; }\n var str = el.style.transform || '';\n var transforms = new Map();\n var m; while (m = transformRegex.exec(str)) { transforms.set(m[1], m[2]); }\n return transforms;\n}\n\nfunction getTransformValue(el, propName, animatable, unit) {\n var defaultVal = stringContains(propName, 'scale') ? 1 : 0 + getTransformUnit(propName);\n var value = getElementTransforms(el).get(propName) || defaultVal;\n if (animatable) {\n animatable.transforms.list.set(propName, value);\n animatable.transforms['last'] = propName;\n }\n return unit ? convertPxToUnit(el, value, unit) : value;\n}\n\nfunction getOriginalTargetValue(target, propName, unit, animatable) {\n switch (getAnimationType(target, propName)) {\n case 'transform': return getTransformValue(target, propName, animatable, unit);\n case 'css': return getCSSValue(target, propName, unit);\n case 'attribute': return getAttribute(target, propName);\n default: return target[propName] || 0;\n }\n}\n\nvar operatorRegex = /^(\\*=|\\+=|-=)/;\n\nfunction getRelativeValue(to, from) {\n var operator = operatorRegex.exec(to);\n if (!operator) { return to; }\n var u = getUnit(to) || 0;\n var x = parseFloat(from);\n var y = parseFloat(to.replace(operator[0], ''));\n switch (operator[0][0]) {\n case '+': return x + y + u;\n case '-': return x - y + u;\n case '*': return x * y + u;\n }\n}\n\nvar whitespaceRegex = /\\s/g;\n\nfunction validateValue(val, unit) {\n if (is.col(val)) { return colorToRgb(val); }\n var originalUnit = getUnit(val);\n var unitLess = originalUnit ? val.substr(0, val.length - originalUnit.length) : val;\n return unit && !whitespaceRegex.test(val) ? unitLess + unit : unitLess;\n}\n\n// getTotalLength() equivalent for circle, rect, polyline, polygon and line shapes\n// adapted from https://gist.github.com/SebLambla/3e0550c496c236709744\n\nfunction getDistance(p1, p2) {\n return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));\n}\n\nfunction getCircleLength(el) {\n return Math.PI * 2 * getAttribute(el, 'r');\n}\n\nfunction getRectLength(el) {\n return (getAttribute(el, 'width') * 2) + (getAttribute(el, 'height') * 2);\n}\n\nfunction getLineLength(el) {\n return getDistance(\n {x: getAttribute(el, 'x1'), y: getAttribute(el, 'y1')},\n {x: getAttribute(el, 'x2'), y: getAttribute(el, 'y2')}\n );\n}\n\nfunction getPolylineLength(el) {\n var points = el.points;\n var totalLength = 0;\n var previousPos;\n for (var i = 0 ; i < points.numberOfItems; i++) {\n var currentPos = points.getItem(i);\n if (i > 0) { totalLength += getDistance(previousPos, currentPos); }\n previousPos = currentPos;\n }\n return totalLength;\n}\n\nfunction getPolygonLength(el) {\n var points = el.points;\n return getPolylineLength(el) + getDistance(points.getItem(points.numberOfItems - 1), points.getItem(0));\n}\n\n// Path animation\n\nfunction getTotalLength(el) {\n if (el.getTotalLength) { return el.getTotalLength(); }\n switch(el.tagName.toLowerCase()) {\n case 'circle': return getCircleLength(el);\n case 'rect': return getRectLength(el);\n case 'line': return getLineLength(el);\n case 'polyline': return getPolylineLength(el);\n case 'polygon': return getPolygonLength(el);\n }\n}\n\nfunction setDashoffset(el) {\n var pathLength = getTotalLength(el);\n el.setAttribute('stroke-dasharray', pathLength);\n return pathLength;\n}\n\n// Motion path\n\nfunction getParentSvgEl(el) {\n var parentEl = el.parentNode;\n while (is.svg(parentEl)) {\n parentEl = parentEl.parentNode;\n if (!is.svg(parentEl.parentNode)) { break; }\n }\n return parentEl;\n}\n\nfunction getParentSvg(pathEl, svgData) {\n var svg = svgData || {};\n var parentSvgEl = svg.el || getParentSvgEl(pathEl);\n var rect = parentSvgEl.getBoundingClientRect();\n var viewBoxAttr = getAttribute(parentSvgEl, 'viewBox');\n var width = rect.width;\n var height = rect.height;\n var viewBox = svg.viewBox || (viewBoxAttr ? viewBoxAttr.split(' ') : [0, 0, width, height]);\n return {\n el: parentSvgEl,\n viewBox: viewBox,\n x: viewBox[0] / 1,\n y: viewBox[1] / 1,\n w: width / viewBox[2],\n h: height / viewBox[3]\n }\n}\n\nfunction getPath(path, percent) {\n var pathEl = is.str(path) ? selectString(path)[0] : path;\n var p = percent || 100;\n return function(property) {\n return {\n property: property,\n el: pathEl,\n svg: getParentSvg(pathEl),\n totalLength: getTotalLength(pathEl) * (p / 100)\n }\n }\n}\n\nfunction getPathProgress(path, progress) {\n function point(offset) {\n if ( offset === void 0 ) offset = 0;\n\n var l = progress + offset >= 1 ? progress + offset : 0;\n return path.el.getPointAtLength(l);\n }\n var svg = getParentSvg(path.el, path.svg);\n var p = point();\n var p0 = point(-1);\n var p1 = point(+1);\n switch (path.property) {\n case 'x': return (p.x - svg.x) * svg.w;\n case 'y': return (p.y - svg.y) * svg.h;\n case 'angle': return Math.atan2(p1.y - p0.y, p1.x - p0.x) * 180 / Math.PI;\n }\n}\n\n// Decompose value\n\nvar valueRegex = /-?\\d*\\.?\\d+/g;\n\nfunction decomposeValue(val, unit) {\n var value = validateValue((is.pth(val) ? val.totalLength : val), unit) + '';\n return {\n original: value,\n numbers: value.match(valueRegex) ? value.match(valueRegex).map(Number) : [0],\n strings: (is.str(val) || unit) ? value.split(valueRegex) : []\n }\n}\n\n// Animatables\n\nfunction parseTargets(targets) {\n var targetsArray = targets ? (flattenArray(is.arr(targets) ? targets.map(toArray) : toArray(targets))) : [];\n return filterArray(targetsArray, function (item, pos, self) { return self.indexOf(item) === pos; });\n}\n\nfunction getAnimatables(targets) {\n var parsed = parseTargets(targets);\n return parsed.map(function (t, i) {\n return {target: t, id: i, total: parsed.length, transforms: { list: getElementTransforms(t) } };\n });\n}\n\n// Properties\n\nvar springRegex = /^spring/;\n\nfunction normalizePropertyTweens(prop, tweenSettings) {\n var settings = cloneObject(tweenSettings);\n // Override duration if easing is a spring\n if (springRegex.test(settings.easing)) { settings.duration = spring(settings.easing); }\n if (is.arr(prop)) {\n var l = prop.length;\n var isFromTo = (l === 2 && !is.obj(prop[0]));\n if (!isFromTo) {\n // Duration divided by the number of tweens\n if (!is.fnc(tweenSettings.duration)) { settings.duration = tweenSettings.duration / l; }\n } else {\n // Transform [from, to] values shorthand to a valid tween value\n prop = {value: prop};\n }\n }\n var propArray = is.arr(prop) ? prop : [prop];\n return propArray.map(function (v, i) {\n var obj = (is.obj(v) && !is.pth(v)) ? v : {value: v};\n // Default delay value should only be applied to the first tween\n if (is.und(obj.delay)) { obj.delay = !i ? tweenSettings.delay : 0; }\n // Default endDelay value should only be applied to the last tween\n if (is.und(obj.endDelay)) { obj.endDelay = i === propArray.length - 1 ? tweenSettings.endDelay : 0; }\n return obj;\n }).map(function (k) { return mergeObjects(k, settings); });\n}\n\n\nfunction flattenKeyframes(keyframes) {\n var propertyNames = filterArray(flattenArray(keyframes.map(function (key) { return Object.keys(key); })), function (p) { return is.key(p); })\n .reduce(function (a,b) { if (a.indexOf(b) < 0) { a.push(b); } return a; }, []);\n var properties = {};\n var loop = function ( i ) {\n var propName = propertyNames[i];\n properties[propName] = keyframes.map(function (key) {\n var newKey = {};\n for (var p in key) {\n if (is.key(p)) {\n if (p == propName) { newKey.value = key[p]; }\n } else {\n newKey[p] = key[p];\n }\n }\n return newKey;\n });\n };\n\n for (var i = 0; i < propertyNames.length; i++) loop( i );\n return properties;\n}\n\nfunction getProperties(tweenSettings, params) {\n var properties = [];\n var keyframes = params.keyframes;\n if (keyframes) { params = mergeObjects(flattenKeyframes(keyframes), params); }\n for (var p in params) {\n if (is.key(p)) {\n properties.push({\n name: p,\n tweens: normalizePropertyTweens(params[p], tweenSettings)\n });\n }\n }\n return properties;\n}\n\n// Tweens\n\nfunction normalizeTweenValues(tween, animatable) {\n var t = {};\n for (var p in tween) {\n var value = getFunctionValue(tween[p], animatable);\n if (is.arr(value)) {\n value = value.map(function (v) { return getFunctionValue(v, animatable); });\n if (value.length === 1) { value = value[0]; }\n }\n t[p] = value;\n }\n t.duration = parseFloat(t.duration);\n t.delay = parseFloat(t.delay);\n return t;\n}\n\nfunction normalizeTweens(prop, animatable) {\n var previousTween;\n return prop.tweens.map(function (t) {\n var tween = normalizeTweenValues(t, animatable);\n var tweenValue = tween.value;\n var to = is.arr(tweenValue) ? tweenValue[1] : tweenValue;\n var toUnit = getUnit(to);\n var originalValue = getOriginalTargetValue(animatable.target, prop.name, toUnit, animatable);\n var previousValue = previousTween ? previousTween.to.original : originalValue;\n var from = is.arr(tweenValue) ? tweenValue[0] : previousValue;\n var fromUnit = getUnit(from) || getUnit(originalValue);\n var unit = toUnit || fromUnit;\n if (is.und(to)) { to = previousValue; }\n tween.from = decomposeValue(from, unit);\n tween.to = decomposeValue(getRelativeValue(to, from), unit);\n tween.start = previousTween ? previousTween.end : 0;\n tween.end = tween.start + tween.delay + tween.duration + tween.endDelay;\n tween.easing = parseEasings(tween.easing, tween.duration);\n tween.isPath = is.pth(tweenValue);\n tween.isColor = is.col(tween.from.original);\n if (tween.isColor) { tween.round = 1; }\n previousTween = tween;\n return tween;\n });\n}\n\n// Tween progress\n\nvar setProgressValue = {\n css: function (t, p, v) { return t.style[p] = v; },\n attribute: function (t, p, v) { return t.setAttribute(p, v); },\n object: function (t, p, v) { return t[p] = v; },\n transform: function (t, p, v, transforms, manual) {\n transforms.list.set(p, v);\n if (p === transforms.last || manual) {\n var str = '';\n transforms.list.forEach(function (value, prop) { str += prop + \"(\" + value + \") \"; });\n t.style.transform = str;\n }\n }\n};\n\n// Set Value helper\n\nfunction setTargetsValue(targets, properties) {\n var animatables = getAnimatables(targets);\n\n for (var i = 0, len = animatables.length; i < len; i++) {\n var animatable = animatables[i];\n\n for (var property in properties) {\n var value = getFunctionValue(properties[property], animatable);\n var target = animatable.target;\n var valueUnit = getUnit(value);\n var originalValue = getOriginalTargetValue(target, property, valueUnit, animatable);\n var unit = valueUnit || getUnit(originalValue);\n var to = getRelativeValue(validateValue(value, unit), originalValue);\n var animType = getAnimationType(target, property);\n setProgressValue[animType](target, property, to, animatable.transforms, true);\n }\n }\n}\n\n// Animations\n\nfunction createAnimation(animatable, prop) {\n var animType = getAnimationType(animatable.target, prop.name);\n if (animType) {\n var tweens = normalizeTweens(prop, animatable);\n var lastTween = tweens[tweens.length - 1];\n return {\n type: animType,\n property: prop.name,\n animatable: animatable,\n tweens: tweens,\n duration: lastTween.end,\n delay: tweens[0].delay,\n endDelay: lastTween.endDelay\n }\n }\n}\n\nfunction getAnimations(animatables, properties) {\n return filterArray(flattenArray(animatables.map(function (animatable) {\n return properties.map(function (prop) {\n return createAnimation(animatable, prop);\n });\n })), function (a) { return !is.und(a); });\n}\n\n// Create Instance\n\nfunction getInstanceTimings(animations, tweenSettings) {\n var animLength = animations.length;\n var getTlOffset = function (anim) { return anim.timelineOffset ? anim.timelineOffset : 0; };\n var timings = {};\n timings.duration = animLength ? Math.max.apply(Math, animations.map(function (anim) { return getTlOffset(anim) + anim.duration; })) : tweenSettings.duration;\n timings.delay = animLength ? Math.min.apply(Math, animations.map(function (anim) { return getTlOffset(anim) + anim.delay; })) : tweenSettings.delay;\n timings.endDelay = animLength ? timings.duration - Math.max.apply(Math, animations.map(function (anim) { return getTlOffset(anim) + anim.duration - anim.endDelay; })) : tweenSettings.endDelay;\n return timings;\n}\n\nvar instanceID = 0;\n\nfunction createNewInstance(params) {\n var instanceSettings = replaceObjectProps(defaultInstanceSettings, params);\n var tweenSettings = replaceObjectProps(defaultTweenSettings, params);\n var properties = getProperties(tweenSettings, params);\n var animatables = getAnimatables(params.targets);\n var animations = getAnimations(animatables, properties);\n var timings = getInstanceTimings(animations, tweenSettings);\n var id = instanceID;\n instanceID++;\n return mergeObjects(instanceSettings, {\n id: id,\n children: [],\n animatables: animatables,\n animations: animations,\n duration: timings.duration,\n delay: timings.delay,\n endDelay: timings.endDelay\n });\n}\n\n// Core\n\nvar activeInstances = [];\nvar pausedInstances = [];\nvar raf;\n\nvar engine = (function () {\n function play() {\n raf = requestAnimationFrame(step);\n }\n function step(t) {\n var activeInstancesLength = activeInstances.length;\n if (activeInstancesLength) {\n var i = 0;\n while (i < activeInstancesLength) {\n var activeInstance = activeInstances[i];\n if (!activeInstance.paused) {\n activeInstance.tick(t);\n } else {\n var instanceIndex = activeInstances.indexOf(activeInstance);\n if (instanceIndex > -1) {\n activeInstances.splice(instanceIndex, 1);\n activeInstancesLength = activeInstances.length;\n }\n }\n i++;\n }\n play();\n } else {\n raf = cancelAnimationFrame(raf);\n }\n }\n return play;\n})();\n\nfunction handleVisibilityChange() {\n if (document.hidden) {\n for (var i = 0, len = activeInstances.length; i < len; i++) {\n activeInstance[i].pause();\n }\n pausedInstances = activeInstances.slice(0);\n activeInstances = [];\n } else {\n for (var i$1 = 0, len$1 = pausedInstances.length; i$1 < len$1; i$1++) {\n pausedInstances[i$1].play();\n }\n }\n}\n\ndocument.addEventListener('visibilitychange', handleVisibilityChange);\n\n// Public Instance\n\nfunction anime(params) {\n if ( params === void 0 ) params = {};\n\n\n var startTime = 0, lastTime = 0, now = 0;\n var children, childrenLength = 0;\n var resolve = null;\n\n function makePromise() {\n return window.Promise && new Promise(function (_resolve) { return resolve = _resolve; });\n }\n\n var promise = makePromise();\n\n var instance = createNewInstance(params);\n\n function toggleInstanceDirection() {\n instance.reversed = !instance.reversed;\n for (var i = 0, len = children.length; i < len; i++) {\n children[i].reversed = instance.reversed;\n }\n }\n\n function adjustTime(time) {\n return instance.reversed ? instance.duration - time : time;\n }\n\n function resetTime() {\n startTime = 0;\n lastTime = adjustTime(instance.currentTime) * (1 / anime.speed);\n }\n\n function seekCild(time, child) {\n if (child) { child.seek(time - child.timelineOffset); }\n }\n\n function syncInstanceChildren(time) {\n if (!instance.reversePlayback) {\n for (var i = 0; i < childrenLength; i++) { seekCild(time, children[i]); }\n } else {\n for (var i$1 = childrenLength; i$1--;) { seekCild(time, children[i$1]); }\n }\n }\n\n function setAnimationsProgress(insTime) {\n var i = 0;\n var animations = instance.animations;\n var animationsLength = animations.length;\n while (i < animationsLength) {\n var anim = animations[i];\n var animatable = anim.animatable;\n var tweens = anim.tweens;\n var tweenLength = tweens.length - 1;\n var tween = tweens[tweenLength];\n // Only check for keyframes if there is more than one tween\n if (tweenLength) { tween = filterArray(tweens, function (t) { return (insTime < t.end); })[0] || tween; }\n var elapsed = minMax(insTime - tween.start - tween.delay, 0, tween.duration) / tween.duration;\n var eased = isNaN(elapsed) ? 1 : tween.easing(elapsed);\n var strings = tween.to.strings;\n var round = tween.round;\n var numbers = [];\n var toNumbersLength = tween.to.numbers.length;\n var progress = (void 0);\n for (var n = 0; n < toNumbersLength; n++) {\n var value = (void 0);\n var toNumber = tween.to.numbers[n];\n var fromNumber = tween.from.numbers[n] || 0;\n if (!tween.isPath) {\n value = fromNumber + (eased * (toNumber - fromNumber));\n } else {\n value = getPathProgress(tween.value, eased * toNumber);\n }\n if (round) {\n if (!(tween.isColor && n > 2)) {\n value = Math.round(value * round) / round;\n }\n }\n numbers.push(value);\n }\n // Manual Array.reduce for better performances\n var stringsLength = strings.length;\n if (!stringsLength) {\n progress = numbers[0];\n } else {\n progress = strings[0];\n for (var s = 0; s < stringsLength; s++) {\n var a = strings[s];\n var b = strings[s + 1];\n var n$1 = numbers[s];\n if (!isNaN(n$1)) {\n if (!b) {\n progress += n$1 + ' ';\n } else {\n progress += n$1 + b;\n }\n }\n }\n }\n setProgressValue[anim.type](animatable.target, anim.property, progress, animatable.transforms);\n anim.currentValue = progress;\n i++;\n }\n }\n\n function setCallback(cb) {\n if (instance[cb] && !instance.passThrough) { instance[cb](instance); }\n }\n\n function countIteration() {\n if (instance.remaining && instance.remaining !== true) {\n instance.remaining--;\n }\n }\n\n function setInstanceProgress(engineTime) {\n var insDuration = instance.duration;\n var insDelay = instance.delay;\n var insEndDelay = insDuration - instance.endDelay;\n var insTime = adjustTime(engineTime);\n instance.progress = minMax((insTime / insDuration) * 100, 0, 100);\n instance.reversePlayback = insTime < instance.currentTime;\n if (children) { syncInstanceChildren(insTime); }\n if (!instance.began && instance.currentTime > 0) {\n instance.began = true;\n setCallback('begin');\n setCallback('loopBegin');\n }\n if (insTime <= insDelay && instance.currentTime !== 0) {\n setAnimationsProgress(0);\n }\n if ((insTime >= insEndDelay && instance.currentTime !== insDuration) || !insDuration) {\n setAnimationsProgress(insDuration);\n }\n if (insTime > insDelay && insTime < insEndDelay) {\n if (!instance.changeBegan) {\n instance.changeBegan = true;\n instance.changeCompleted = false;\n setCallback('changeBegin');\n }\n setCallback('change');\n setAnimationsProgress(insTime);\n } else {\n if (instance.changeBegan) {\n instance.changeCompleted = true;\n instance.changeBegan = false;\n setCallback('changeComplete');\n }\n }\n instance.currentTime = minMax(insTime, 0, insDuration);\n if (instance.began) { setCallback('update'); }\n if (engineTime >= insDuration) {\n lastTime = 0;\n countIteration();\n if (instance.remaining) {\n startTime = now;\n setCallback('loopComplete');\n setCallback('loopBegin');\n if (instance.direction === 'alternate') { toggleInstanceDirection(); }\n } else {\n instance.paused = true;\n if (!instance.completed) {\n instance.completed = true;\n setCallback('loopComplete');\n setCallback('complete');\n if ('Promise' in window) {\n resolve();\n promise = makePromise();\n }\n }\n }\n }\n }\n\n instance.reset = function() {\n var direction = instance.direction;\n instance.passThrough = false;\n instance.currentTime = 0;\n instance.progress = 0;\n instance.paused = true;\n instance.began = false;\n instance.changeBegan = false;\n instance.completed = false;\n instance.changeCompleted = false;\n instance.reversePlayback = false;\n instance.reversed = direction === 'reverse';\n instance.remaining = instance.loop;\n children = instance.children;\n childrenLength = children.length;\n for (var i = childrenLength; i--;) { instance.children[i].reset(); }\n if (instance.reversed && instance.loop !== true || (direction === 'alternate' && instance.loop === 1)) { instance.remaining++; }\n setAnimationsProgress(0);\n };\n\n // Set Value helper\n\n instance.set = function(targets, properties) {\n setTargetsValue(targets, properties);\n return instance;\n };\n\n instance.tick = function(t) {\n now = t;\n if (!startTime) { startTime = now; }\n setInstanceProgress((now + (lastTime - startTime)) * anime.speed);\n };\n\n instance.seek = function(time) {\n setInstanceProgress(adjustTime(time));\n };\n\n instance.pause = function() {\n instance.paused = true;\n resetTime();\n };\n\n instance.play = function() {\n if (!instance.paused) { return; }\n instance.paused = false;\n activeInstances.push(instance);\n resetTime();\n if (!raf) { engine(); }\n };\n\n instance.reverse = function() {\n toggleInstanceDirection();\n resetTime();\n };\n\n instance.restart = function() {\n instance.reset();\n instance.play();\n };\n\n instance.finished = promise;\n instance.reset();\n\n if (instance.autoplay) { instance.play(); }\n\n return instance;\n\n}\n\n// Remove targets from animation\n\nfunction removeTargetsFromAnimations(targetsArray, animations) {\n for (var a = animations.length; a--;) {\n if (arrayContains(targetsArray, animations[a].animatable.target)) {\n animations.splice(a, 1);\n }\n }\n}\n\nfunction removeTargets(targets) {\n var targetsArray = parseTargets(targets);\n for (var i = activeInstances.length; i--;) {\n var instance = activeInstances[i];\n var animations = instance.animations;\n var children = instance.children;\n removeTargetsFromAnimations(targetsArray, animations);\n for (var c = children.length; c--;) {\n var child = children[c];\n var childAnimations = child.animations;\n removeTargetsFromAnimations(targetsArray, childAnimations);\n if (!childAnimations.length && !child.children.length) { children.splice(c, 1); }\n }\n if (!animations.length && !children.length) { instance.pause(); }\n }\n}\n\n// Stagger helpers\n\nfunction stagger(val, params) {\n if ( params === void 0 ) params = {};\n\n var direction = params.direction || 'normal';\n var easing = params.easing ? parseEasings(params.easing) : null;\n var grid = params.grid;\n var axis = params.axis;\n var fromIndex = params.from || 0;\n var fromFirst = fromIndex === 'first';\n var fromCenter = fromIndex === 'center';\n var fromLast = fromIndex === 'last';\n var isRange = is.arr(val);\n var val1 = isRange ? parseFloat(val[0]) : parseFloat(val);\n var val2 = isRange ? parseFloat(val[1]) : 0;\n var unit = getUnit(isRange ? val[1] : val) || 0;\n var start = params.start || 0 + (isRange ? val1 : 0);\n var values = [];\n var maxValue = 0;\n return function (el, i, t) {\n if (fromFirst) { fromIndex = 0; }\n if (fromCenter) { fromIndex = (t - 1) / 2; }\n if (fromLast) { fromIndex = t - 1; }\n if (!values.length) {\n for (var index = 0; index < t; index++) {\n if (!grid) {\n values.push(Math.abs(fromIndex - index));\n } else {\n var fromX = !fromCenter ? fromIndex%grid[0] : (grid[0]-1)/2;\n var fromY = !fromCenter ? Math.floor(fromIndex/grid[0]) : (grid[1]-1)/2;\n var toX = index%grid[0];\n var toY = Math.floor(index/grid[0]);\n var distanceX = fromX - toX;\n var distanceY = fromY - toY;\n var value = Math.sqrt(distanceX * distanceX + distanceY * distanceY);\n if (axis === 'x') { value = -distanceX; }\n if (axis === 'y') { value = -distanceY; }\n values.push(value);\n }\n maxValue = Math.max.apply(Math, values);\n }\n if (easing) { values = values.map(function (val) { return easing(val / maxValue) * maxValue; }); }\n if (direction === 'reverse') { values = values.map(function (val) { return axis ? (val < 0) ? val * -1 : -val : Math.abs(maxValue - val); }); }\n }\n var spacing = isRange ? (val2 - val1) / maxValue : val1;\n return start + (spacing * (Math.round(values[i] * 100) / 100)) + unit;\n }\n}\n\n// Timeline\n\nfunction timeline(params) {\n if ( params === void 0 ) params = {};\n\n var tl = anime(params);\n tl.duration = 0;\n tl.add = function(instanceParams, timelineOffset) {\n var tlIndex = activeInstances.indexOf(tl);\n var children = tl.children;\n if (tlIndex > -1) { activeInstances.splice(tlIndex, 1); }\n function passThrough(ins) { ins.passThrough = true; }\n for (var i = 0; i < children.length; i++) { passThrough(children[i]); }\n var insParams = mergeObjects(instanceParams, replaceObjectProps(defaultTweenSettings, params));\n insParams.targets = insParams.targets || params.targets;\n var tlDuration = tl.duration;\n insParams.autoplay = false;\n insParams.direction = tl.direction;\n insParams.timelineOffset = is.und(timelineOffset) ? tlDuration : getRelativeValue(timelineOffset, tlDuration);\n passThrough(tl);\n tl.seek(insParams.timelineOffset);\n var ins = anime(insParams);\n passThrough(ins);\n children.push(ins);\n var timings = getInstanceTimings(children, params);\n tl.delay = timings.delay;\n tl.endDelay = timings.endDelay;\n tl.duration = timings.duration;\n tl.seek(0);\n tl.reset();\n if (tl.autoplay) { tl.play(); }\n return tl;\n };\n return tl;\n}\n\nanime.version = '3.0.0';\nanime.speed = 1;\nanime.running = activeInstances;\nanime.remove = removeTargets;\nanime.get = getOriginalTargetValue;\nanime.set = setTargetsValue;\nanime.convertPx = convertPxToUnit;\nanime.path = getPath;\nanime.setDashoffset = setDashoffset;\nanime.stagger = stagger;\nanime.timeline = timeline;\nanime.easing = parseEasings;\nanime.penner = penner;\nanime.random = function (min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; };\n\nmodule.exports = anime;\n", - "(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(global = global || self, factory(global.THREE = {}));\n}(this, function (exports) { 'use strict';\n\n\t// Polyfills\r\n\r\n\tif ( Number.EPSILON === undefined ) {\r\n\r\n\t\tNumber.EPSILON = Math.pow( 2, - 52 );\r\n\r\n\t}\r\n\r\n\tif ( Number.isInteger === undefined ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger\r\n\r\n\t\tNumber.isInteger = function ( value ) {\r\n\r\n\t\t\treturn typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tif ( Math.sign === undefined ) {\r\n\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign\r\n\r\n\t\tMath.sign = function ( x ) {\r\n\r\n\t\t\treturn ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tif ( 'name' in Function.prototype === false ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name\r\n\r\n\t\tObject.defineProperty( Function.prototype, 'name', {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.toString().match( /^\\s*function\\s*([^\\(\\s]*)/ )[ 1 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\tif ( Object.assign === undefined ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\r\n\r\n\t\tObject.assign = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined || target === null ) {\r\n\r\n\t\t\t\tthrow new TypeError( 'Cannot convert undefined or null to object' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar output = Object( target );\r\n\r\n\t\t\tfor ( var index = 1; index < arguments.length; index ++ ) {\r\n\r\n\t\t\t\tvar source = arguments[ index ];\r\n\r\n\t\t\t\tif ( source !== undefined && source !== null ) {\r\n\r\n\t\t\t\t\tfor ( var nextKey in source ) {\r\n\r\n\t\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {\r\n\r\n\t\t\t\t\t\t\toutput[ nextKey ] = source[ nextKey ];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t};\r\n\r\n\t}\n\n\tvar REVISION = '111dev';\r\n\tvar MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };\r\n\tvar TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };\r\n\tvar CullFaceNone = 0;\r\n\tvar CullFaceBack = 1;\r\n\tvar CullFaceFront = 2;\r\n\tvar CullFaceFrontBack = 3;\r\n\tvar FrontFaceDirectionCW = 0;\r\n\tvar FrontFaceDirectionCCW = 1;\r\n\tvar BasicShadowMap = 0;\r\n\tvar PCFShadowMap = 1;\r\n\tvar PCFSoftShadowMap = 2;\r\n\tvar VSMShadowMap = 3;\r\n\tvar FrontSide = 0;\r\n\tvar BackSide = 1;\r\n\tvar DoubleSide = 2;\r\n\tvar FlatShading = 1;\r\n\tvar SmoothShading = 2;\r\n\tvar NoColors = 0;\r\n\tvar FaceColors = 1;\r\n\tvar VertexColors = 2;\r\n\tvar NoBlending = 0;\r\n\tvar NormalBlending = 1;\r\n\tvar AdditiveBlending = 2;\r\n\tvar SubtractiveBlending = 3;\r\n\tvar MultiplyBlending = 4;\r\n\tvar CustomBlending = 5;\r\n\tvar AddEquation = 100;\r\n\tvar SubtractEquation = 101;\r\n\tvar ReverseSubtractEquation = 102;\r\n\tvar MinEquation = 103;\r\n\tvar MaxEquation = 104;\r\n\tvar ZeroFactor = 200;\r\n\tvar OneFactor = 201;\r\n\tvar SrcColorFactor = 202;\r\n\tvar OneMinusSrcColorFactor = 203;\r\n\tvar SrcAlphaFactor = 204;\r\n\tvar OneMinusSrcAlphaFactor = 205;\r\n\tvar DstAlphaFactor = 206;\r\n\tvar OneMinusDstAlphaFactor = 207;\r\n\tvar DstColorFactor = 208;\r\n\tvar OneMinusDstColorFactor = 209;\r\n\tvar SrcAlphaSaturateFactor = 210;\r\n\tvar NeverDepth = 0;\r\n\tvar AlwaysDepth = 1;\r\n\tvar LessDepth = 2;\r\n\tvar LessEqualDepth = 3;\r\n\tvar EqualDepth = 4;\r\n\tvar GreaterEqualDepth = 5;\r\n\tvar GreaterDepth = 6;\r\n\tvar NotEqualDepth = 7;\r\n\tvar MultiplyOperation = 0;\r\n\tvar MixOperation = 1;\r\n\tvar AddOperation = 2;\r\n\tvar NoToneMapping = 0;\r\n\tvar LinearToneMapping = 1;\r\n\tvar ReinhardToneMapping = 2;\r\n\tvar Uncharted2ToneMapping = 3;\r\n\tvar CineonToneMapping = 4;\r\n\tvar ACESFilmicToneMapping = 5;\r\n\r\n\tvar UVMapping = 300;\r\n\tvar CubeReflectionMapping = 301;\r\n\tvar CubeRefractionMapping = 302;\r\n\tvar EquirectangularReflectionMapping = 303;\r\n\tvar EquirectangularRefractionMapping = 304;\r\n\tvar SphericalReflectionMapping = 305;\r\n\tvar CubeUVReflectionMapping = 306;\r\n\tvar CubeUVRefractionMapping = 307;\r\n\tvar RepeatWrapping = 1000;\r\n\tvar ClampToEdgeWrapping = 1001;\r\n\tvar MirroredRepeatWrapping = 1002;\r\n\tvar NearestFilter = 1003;\r\n\tvar NearestMipmapNearestFilter = 1004;\r\n\tvar NearestMipMapNearestFilter = 1004;\r\n\tvar NearestMipmapLinearFilter = 1005;\r\n\tvar NearestMipMapLinearFilter = 1005;\r\n\tvar LinearFilter = 1006;\r\n\tvar LinearMipmapNearestFilter = 1007;\r\n\tvar LinearMipMapNearestFilter = 1007;\r\n\tvar LinearMipmapLinearFilter = 1008;\r\n\tvar LinearMipMapLinearFilter = 1008;\r\n\tvar UnsignedByteType = 1009;\r\n\tvar ByteType = 1010;\r\n\tvar ShortType = 1011;\r\n\tvar UnsignedShortType = 1012;\r\n\tvar IntType = 1013;\r\n\tvar UnsignedIntType = 1014;\r\n\tvar FloatType = 1015;\r\n\tvar HalfFloatType = 1016;\r\n\tvar UnsignedShort4444Type = 1017;\r\n\tvar UnsignedShort5551Type = 1018;\r\n\tvar UnsignedShort565Type = 1019;\r\n\tvar UnsignedInt248Type = 1020;\r\n\tvar AlphaFormat = 1021;\r\n\tvar RGBFormat = 1022;\r\n\tvar RGBAFormat = 1023;\r\n\tvar LuminanceFormat = 1024;\r\n\tvar LuminanceAlphaFormat = 1025;\r\n\tvar RGBEFormat = RGBAFormat;\r\n\tvar DepthFormat = 1026;\r\n\tvar DepthStencilFormat = 1027;\r\n\tvar RedFormat = 1028;\r\n\tvar RGB_S3TC_DXT1_Format = 33776;\r\n\tvar RGBA_S3TC_DXT1_Format = 33777;\r\n\tvar RGBA_S3TC_DXT3_Format = 33778;\r\n\tvar RGBA_S3TC_DXT5_Format = 33779;\r\n\tvar RGB_PVRTC_4BPPV1_Format = 35840;\r\n\tvar RGB_PVRTC_2BPPV1_Format = 35841;\r\n\tvar RGBA_PVRTC_4BPPV1_Format = 35842;\r\n\tvar RGBA_PVRTC_2BPPV1_Format = 35843;\r\n\tvar RGB_ETC1_Format = 36196;\r\n\tvar RGBA_ASTC_4x4_Format = 37808;\r\n\tvar RGBA_ASTC_5x4_Format = 37809;\r\n\tvar RGBA_ASTC_5x5_Format = 37810;\r\n\tvar RGBA_ASTC_6x5_Format = 37811;\r\n\tvar RGBA_ASTC_6x6_Format = 37812;\r\n\tvar RGBA_ASTC_8x5_Format = 37813;\r\n\tvar RGBA_ASTC_8x6_Format = 37814;\r\n\tvar RGBA_ASTC_8x8_Format = 37815;\r\n\tvar RGBA_ASTC_10x5_Format = 37816;\r\n\tvar RGBA_ASTC_10x6_Format = 37817;\r\n\tvar RGBA_ASTC_10x8_Format = 37818;\r\n\tvar RGBA_ASTC_10x10_Format = 37819;\r\n\tvar RGBA_ASTC_12x10_Format = 37820;\r\n\tvar RGBA_ASTC_12x12_Format = 37821;\r\n\tvar LoopOnce = 2200;\r\n\tvar LoopRepeat = 2201;\r\n\tvar LoopPingPong = 2202;\r\n\tvar InterpolateDiscrete = 2300;\r\n\tvar InterpolateLinear = 2301;\r\n\tvar InterpolateSmooth = 2302;\r\n\tvar ZeroCurvatureEnding = 2400;\r\n\tvar ZeroSlopeEnding = 2401;\r\n\tvar WrapAroundEnding = 2402;\r\n\tvar TrianglesDrawMode = 0;\r\n\tvar TriangleStripDrawMode = 1;\r\n\tvar TriangleFanDrawMode = 2;\r\n\tvar LinearEncoding = 3000;\r\n\tvar sRGBEncoding = 3001;\r\n\tvar GammaEncoding = 3007;\r\n\tvar RGBEEncoding = 3002;\r\n\tvar LogLuvEncoding = 3003;\r\n\tvar RGBM7Encoding = 3004;\r\n\tvar RGBM16Encoding = 3005;\r\n\tvar RGBDEncoding = 3006;\r\n\tvar BasicDepthPacking = 3200;\r\n\tvar RGBADepthPacking = 3201;\r\n\tvar TangentSpaceNormalMap = 0;\r\n\tvar ObjectSpaceNormalMap = 1;\r\n\r\n\tvar ZeroStencilOp = 0;\r\n\tvar KeepStencilOp = 7680;\r\n\tvar ReplaceStencilOp = 7681;\r\n\tvar IncrementStencilOp = 7682;\r\n\tvar DecrementStencilOp = 7683;\r\n\tvar IncrementWrapStencilOp = 34055;\r\n\tvar DecrementWrapStencilOp = 34056;\r\n\tvar InvertStencilOp = 5386;\r\n\r\n\tvar NeverStencilFunc = 512;\r\n\tvar LessStencilFunc = 513;\r\n\tvar EqualStencilFunc = 514;\r\n\tvar LessEqualStencilFunc = 515;\r\n\tvar GreaterStencilFunc = 516;\r\n\tvar NotEqualStencilFunc = 517;\r\n\tvar GreaterEqualStencilFunc = 518;\r\n\tvar AlwaysStencilFunc = 519;\r\n\r\n\tvar StaticDrawUsage = 35044;\r\n\tvar DynamicDrawUsage = 35048;\r\n\tvar StreamDrawUsage = 35040;\r\n\tvar StaticReadUsage = 35045;\r\n\tvar DynamicReadUsage = 35049;\r\n\tvar StreamReadUsage = 35041;\r\n\tvar StaticCopyUsage = 35046;\r\n\tvar DynamicCopyUsage = 35050;\r\n\tvar StreamCopyUsage = 35042;\n\n\t/**\r\n\t * https://github.com/mrdoob/eventdispatcher.js/\r\n\t */\r\n\r\n\tfunction EventDispatcher() {}\r\n\r\n\tObject.assign( EventDispatcher.prototype, {\r\n\r\n\t\taddEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { this._listeners = {}; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\r\n\t\t\tif ( listeners[ type ] === undefined ) {\r\n\r\n\t\t\t\tlisteners[ type ] = [];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( listeners[ type ].indexOf( listener ) === - 1 ) {\r\n\r\n\t\t\t\tlisteners[ type ].push( listener );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\thasEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return false; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\r\n\t\t\treturn listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;\r\n\r\n\t\t},\r\n\r\n\t\tremoveEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\t\t\tvar listenerArray = listeners[ type ];\r\n\r\n\t\t\tif ( listenerArray !== undefined ) {\r\n\r\n\t\t\t\tvar index = listenerArray.indexOf( listener );\r\n\r\n\t\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\t\tlistenerArray.splice( index, 1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tdispatchEvent: function ( event ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\t\t\tvar listenerArray = listeners[ event.type ];\r\n\r\n\t\t\tif ( listenerArray !== undefined ) {\r\n\r\n\t\t\t\tevent.target = this;\r\n\r\n\t\t\t\tvar array = listenerArray.slice( 0 );\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tarray[ i ].call( this, event );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _lut = [];\r\n\r\n\tfor ( var i = 0; i < 256; i ++ ) {\r\n\r\n\t\t_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );\r\n\r\n\t}\r\n\r\n\tvar _Math = {\r\n\r\n\t\tDEG2RAD: Math.PI / 180,\r\n\t\tRAD2DEG: 180 / Math.PI,\r\n\r\n\t\tgenerateUUID: function () {\r\n\r\n\t\t\t// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136\r\n\r\n\t\t\tvar d0 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d1 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d2 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d3 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +\r\n\t\t\t\t_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +\r\n\t\t\t\t_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +\r\n\t\t\t\t_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];\r\n\r\n\t\t\t// .toUpperCase() here flattens concatenated strings to save heap memory space.\r\n\t\t\treturn uuid.toUpperCase();\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( value, min, max ) {\r\n\r\n\t\t\treturn Math.max( min, Math.min( max, value ) );\r\n\r\n\t\t},\r\n\r\n\t\t// compute euclidian modulo of m % n\r\n\t\t// https://en.wikipedia.org/wiki/Modulo_operation\r\n\r\n\t\teuclideanModulo: function ( n, m ) {\r\n\r\n\t\t\treturn ( ( n % m ) + m ) % m;\r\n\r\n\t\t},\r\n\r\n\t\t// Linear mapping from range to range \r\n\r\n\t\tmapLinear: function ( x, a1, a2, b1, b2 ) {\r\n\r\n\t\t\treturn b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );\r\n\r\n\t\t},\r\n\r\n\t\t// https://en.wikipedia.org/wiki/Linear_interpolation\r\n\r\n\t\tlerp: function ( x, y, t ) {\r\n\r\n\t\t\treturn ( 1 - t ) * x + t * y;\r\n\r\n\t\t},\r\n\r\n\t\t// http://en.wikipedia.org/wiki/Smoothstep\r\n\r\n\t\tsmoothstep: function ( x, min, max ) {\r\n\r\n\t\t\tif ( x <= min ) { return 0; }\r\n\t\t\tif ( x >= max ) { return 1; }\r\n\r\n\t\t\tx = ( x - min ) / ( max - min );\r\n\r\n\t\t\treturn x * x * ( 3 - 2 * x );\r\n\r\n\t\t},\r\n\r\n\t\tsmootherstep: function ( x, min, max ) {\r\n\r\n\t\t\tif ( x <= min ) { return 0; }\r\n\t\t\tif ( x >= max ) { return 1; }\r\n\r\n\t\t\tx = ( x - min ) / ( max - min );\r\n\r\n\t\t\treturn x * x * x * ( x * ( x * 6 - 15 ) + 10 );\r\n\r\n\t\t},\r\n\r\n\t\t// Random integer from interval\r\n\r\n\t\trandInt: function ( low, high ) {\r\n\r\n\t\t\treturn low + Math.floor( Math.random() * ( high - low + 1 ) );\r\n\r\n\t\t},\r\n\r\n\t\t// Random float from interval\r\n\r\n\t\trandFloat: function ( low, high ) {\r\n\r\n\t\t\treturn low + Math.random() * ( high - low );\r\n\r\n\t\t},\r\n\r\n\t\t// Random float from <-range/2, range/2> interval\r\n\r\n\t\trandFloatSpread: function ( range ) {\r\n\r\n\t\t\treturn range * ( 0.5 - Math.random() );\r\n\r\n\t\t},\r\n\r\n\t\tdegToRad: function ( degrees ) {\r\n\r\n\t\t\treturn degrees * _Math.DEG2RAD;\r\n\r\n\t\t},\r\n\r\n\t\tradToDeg: function ( radians ) {\r\n\r\n\t\t\treturn radians * _Math.RAD2DEG;\r\n\r\n\t\t},\r\n\r\n\t\tisPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn ( value & ( value - 1 ) ) === 0 && value !== 0;\r\n\r\n\t\t},\r\n\r\n\t\tceilPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloorPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t */\r\n\r\n\tfunction Vector2( x, y ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( Vector2.prototype, {\r\n\r\n\t\t\"width\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.x = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t\"height\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.y = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector2.prototype, {\r\n\r\n\t\tisVector2: true,\r\n\r\n\t\tset: function ( x, y ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( v ) {\r\n\r\n\t\t\tthis.x *= v.x;\r\n\t\t\tthis.y *= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivide: function ( v ) {\r\n\r\n\t\t\tthis.x /= v.x;\r\n\t\t\tthis.y /= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y;\r\n\r\n\t\t},\r\n\r\n\t\tcross: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.y - this.y * v.x;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tangle: function () {\r\n\r\n\t\t\t// computes the angle in radians with respect to the positive x-axis\r\n\r\n\t\t\tvar angle = Math.atan2( this.y, this.x );\r\n\r\n\t\t\tif ( angle < 0 ) { angle += 2 * Math.PI; }\r\n\r\n\t\t\treturn angle;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceToSquared( v ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSquared: function ( v ) {\r\n\r\n\t\t\tvar dx = this.x - v.x, dy = this.y - v.y;\r\n\t\t\treturn dx * dx + dy * dy;\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanDistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateAround: function ( center, angle ) {\r\n\r\n\t\t\tvar c = Math.cos( angle ), s = Math.sin( angle );\r\n\r\n\t\t\tvar x = this.x - center.x;\r\n\t\t\tvar y = this.y - center.y;\r\n\r\n\t\t\tthis.x = x * c - y * s + center.x;\r\n\t\t\tthis.y = x * s + y * c + center.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tfunction Quaternion( x, y, z, w ) {\r\n\r\n\t\tthis._x = x || 0;\r\n\t\tthis._y = y || 0;\r\n\t\tthis._z = z || 0;\r\n\t\tthis._w = ( w !== undefined ) ? w : 1;\r\n\r\n\t}\r\n\r\n\tObject.assign( Quaternion, {\r\n\r\n\t\tslerp: function ( qa, qb, qm, t ) {\r\n\r\n\t\t\treturn qm.copy( qa ).slerp( qb, t );\r\n\r\n\t\t},\r\n\r\n\t\tslerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {\r\n\r\n\t\t\t// fuzz-free, array-based Quaternion SLERP operation\r\n\r\n\t\t\tvar x0 = src0[ srcOffset0 + 0 ],\r\n\t\t\t\ty0 = src0[ srcOffset0 + 1 ],\r\n\t\t\t\tz0 = src0[ srcOffset0 + 2 ],\r\n\t\t\t\tw0 = src0[ srcOffset0 + 3 ],\r\n\r\n\t\t\t\tx1 = src1[ srcOffset1 + 0 ],\r\n\t\t\t\ty1 = src1[ srcOffset1 + 1 ],\r\n\t\t\t\tz1 = src1[ srcOffset1 + 2 ],\r\n\t\t\t\tw1 = src1[ srcOffset1 + 3 ];\r\n\r\n\t\t\tif ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {\r\n\r\n\t\t\t\tvar s = 1 - t,\r\n\r\n\t\t\t\t\tcos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,\r\n\r\n\t\t\t\t\tdir = ( cos >= 0 ? 1 : - 1 ),\r\n\t\t\t\t\tsqrSin = 1 - cos * cos;\r\n\r\n\t\t\t\t// Skip the Slerp for tiny steps to avoid numeric problems:\r\n\t\t\t\tif ( sqrSin > Number.EPSILON ) {\r\n\r\n\t\t\t\t\tvar sin = Math.sqrt( sqrSin ),\r\n\t\t\t\t\t\tlen = Math.atan2( sin, cos * dir );\r\n\r\n\t\t\t\t\ts = Math.sin( s * len ) / sin;\r\n\t\t\t\t\tt = Math.sin( t * len ) / sin;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar tDir = t * dir;\r\n\r\n\t\t\t\tx0 = x0 * s + x1 * tDir;\r\n\t\t\t\ty0 = y0 * s + y1 * tDir;\r\n\t\t\t\tz0 = z0 * s + z1 * tDir;\r\n\t\t\t\tw0 = w0 * s + w1 * tDir;\r\n\r\n\t\t\t\t// Normalize in case we just did a lerp:\r\n\t\t\t\tif ( s === 1 - t ) {\r\n\r\n\t\t\t\t\tvar f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );\r\n\r\n\t\t\t\t\tx0 *= f;\r\n\t\t\t\t\ty0 *= f;\r\n\t\t\t\t\tz0 *= f;\r\n\t\t\t\t\tw0 *= f;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdst[ dstOffset ] = x0;\r\n\t\t\tdst[ dstOffset + 1 ] = y0;\r\n\t\t\tdst[ dstOffset + 2 ] = z0;\r\n\t\t\tdst[ dstOffset + 3 ] = w0;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Quaternion.prototype, {\r\n\r\n\t\tx: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._x = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ty: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._y = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tz: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._z = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tw: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._w;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._w = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Quaternion.prototype, {\r\n\r\n\t\tisQuaternion: true,\r\n\r\n\t\tset: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis._x = x;\r\n\t\t\tthis._y = y;\r\n\t\t\tthis._z = z;\r\n\t\t\tthis._w = w;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this._x, this._y, this._z, this._w );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( quaternion ) {\r\n\r\n\t\t\tthis._x = quaternion.x;\r\n\t\t\tthis._y = quaternion.y;\r\n\t\t\tthis._z = quaternion.z;\r\n\t\t\tthis._w = quaternion.w;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromEuler: function ( euler, update ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tthrow new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar x = euler._x, y = euler._y, z = euler._z, order = euler.order;\r\n\r\n\t\t\t// http://www.mathworks.com/matlabcentral/fileexchange/\r\n\t\t\t// \t20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\r\n\t\t\t//\tcontent/SpinCalc.m\r\n\r\n\t\t\tvar cos = Math.cos;\r\n\t\t\tvar sin = Math.sin;\r\n\r\n\t\t\tvar c1 = cos( x / 2 );\r\n\t\t\tvar c2 = cos( y / 2 );\r\n\t\t\tvar c3 = cos( z / 2 );\r\n\r\n\t\t\tvar s1 = sin( x / 2 );\r\n\t\t\tvar s2 = sin( y / 2 );\r\n\t\t\tvar s3 = sin( z / 2 );\r\n\r\n\t\t\tif ( order === 'XYZ' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'YXZ' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'ZXY' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'ZYX' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'YZX' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'XZY' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( update !== false ) { this._onChangeCallback(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\r\n\r\n\t\t\t// assumes axis is normalized\r\n\r\n\t\t\tvar halfAngle = angle / 2, s = Math.sin( halfAngle );\r\n\r\n\t\t\tthis._x = axis.x * s;\r\n\t\t\tthis._y = axis.y * s;\r\n\t\t\tthis._z = axis.z * s;\r\n\t\t\tthis._w = Math.cos( halfAngle );\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromRotationMatrix: function ( m ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar te = m.elements,\r\n\r\n\t\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\r\n\t\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\r\n\t\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],\r\n\r\n\t\t\t\ttrace = m11 + m22 + m33,\r\n\t\t\t\ts;\r\n\r\n\t\t\tif ( trace > 0 ) {\r\n\r\n\t\t\t\ts = 0.5 / Math.sqrt( trace + 1.0 );\r\n\r\n\t\t\t\tthis._w = 0.25 / s;\r\n\t\t\t\tthis._x = ( m32 - m23 ) * s;\r\n\t\t\t\tthis._y = ( m13 - m31 ) * s;\r\n\t\t\t\tthis._z = ( m21 - m12 ) * s;\r\n\r\n\t\t\t} else if ( m11 > m22 && m11 > m33 ) {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );\r\n\r\n\t\t\t\tthis._w = ( m32 - m23 ) / s;\r\n\t\t\t\tthis._x = 0.25 * s;\r\n\t\t\t\tthis._y = ( m12 + m21 ) / s;\r\n\t\t\t\tthis._z = ( m13 + m31 ) / s;\r\n\r\n\t\t\t} else if ( m22 > m33 ) {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );\r\n\r\n\t\t\t\tthis._w = ( m13 - m31 ) / s;\r\n\t\t\t\tthis._x = ( m12 + m21 ) / s;\r\n\t\t\t\tthis._y = 0.25 * s;\r\n\t\t\t\tthis._z = ( m23 + m32 ) / s;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );\r\n\r\n\t\t\t\tthis._w = ( m21 - m12 ) / s;\r\n\t\t\t\tthis._x = ( m13 + m31 ) / s;\r\n\t\t\t\tthis._y = ( m23 + m32 ) / s;\r\n\t\t\t\tthis._z = 0.25 * s;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromUnitVectors: function ( vFrom, vTo ) {\r\n\r\n\t\t\t// assumes direction vectors vFrom and vTo are normalized\r\n\r\n\t\t\tvar EPS = 0.000001;\r\n\r\n\t\t\tvar r = vFrom.dot( vTo ) + 1;\r\n\r\n\t\t\tif ( r < EPS ) {\r\n\r\n\t\t\t\tr = 0;\r\n\r\n\t\t\t\tif ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {\r\n\r\n\t\t\t\t\tthis._x = - vFrom.y;\r\n\t\t\t\t\tthis._y = vFrom.x;\r\n\t\t\t\t\tthis._z = 0;\r\n\t\t\t\t\tthis._w = r;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._y = - vFrom.z;\r\n\t\t\t\t\tthis._z = vFrom.y;\r\n\t\t\t\t\tthis._w = r;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3\r\n\r\n\t\t\t\tthis._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\r\n\t\t\t\tthis._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\r\n\t\t\t\tthis._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\r\n\t\t\t\tthis._w = r;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tangleTo: function ( q ) {\r\n\r\n\t\t\treturn 2 * Math.acos( Math.abs( _Math.clamp( this.dot( q ), - 1, 1 ) ) );\r\n\r\n\t\t},\r\n\r\n\t\trotateTowards: function ( q, step ) {\r\n\r\n\t\t\tvar angle = this.angleTo( q );\r\n\r\n\t\t\tif ( angle === 0 ) { return this; }\r\n\r\n\t\t\tvar t = Math.min( 1, step / angle );\r\n\r\n\t\t\tthis.slerp( q, t );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tinverse: function () {\r\n\r\n\t\t\t// quaternion is assumed to have unit length\r\n\r\n\t\t\treturn this.conjugate();\r\n\r\n\t\t},\r\n\r\n\t\tconjugate: function () {\r\n\r\n\t\t\tthis._x *= - 1;\r\n\t\t\tthis._y *= - 1;\r\n\t\t\tthis._z *= - 1;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\tvar l = this.length();\r\n\r\n\t\t\tif ( l === 0 ) {\r\n\r\n\t\t\t\tthis._x = 0;\r\n\t\t\t\tthis._y = 0;\r\n\t\t\t\tthis._z = 0;\r\n\t\t\t\tthis._w = 1;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tl = 1 / l;\r\n\r\n\t\t\t\tthis._x = this._x * l;\r\n\t\t\t\tthis._y = this._y * l;\r\n\t\t\t\tthis._z = this._z * l;\r\n\t\t\t\tthis._w = this._w * l;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( q, p ) {\r\n\r\n\t\t\tif ( p !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyQuaternions( q, p );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.multiplyQuaternions( this, q );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( q ) {\r\n\r\n\t\t\treturn this.multiplyQuaternions( q, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyQuaternions: function ( a, b ) {\r\n\r\n\t\t\t// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm\r\n\r\n\t\t\tvar qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\r\n\t\t\tvar qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\r\n\r\n\t\t\tthis._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\r\n\t\t\tthis._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\r\n\t\t\tthis._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\r\n\t\t\tthis._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tslerp: function ( qb, t ) {\r\n\r\n\t\t\tif ( t === 0 ) { return this; }\r\n\t\t\tif ( t === 1 ) { return this.copy( qb ); }\r\n\r\n\t\t\tvar x = this._x, y = this._y, z = this._z, w = this._w;\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/\r\n\r\n\t\t\tvar cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;\r\n\r\n\t\t\tif ( cosHalfTheta < 0 ) {\r\n\r\n\t\t\t\tthis._w = - qb._w;\r\n\t\t\t\tthis._x = - qb._x;\r\n\t\t\t\tthis._y = - qb._y;\r\n\t\t\t\tthis._z = - qb._z;\r\n\r\n\t\t\t\tcosHalfTheta = - cosHalfTheta;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.copy( qb );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( cosHalfTheta >= 1.0 ) {\r\n\r\n\t\t\t\tthis._w = w;\r\n\t\t\t\tthis._x = x;\r\n\t\t\t\tthis._y = y;\r\n\t\t\t\tthis._z = z;\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;\r\n\r\n\t\t\tif ( sqrSinHalfTheta <= Number.EPSILON ) {\r\n\r\n\t\t\t\tvar s = 1 - t;\r\n\t\t\t\tthis._w = s * w + t * this._w;\r\n\t\t\t\tthis._x = s * x + t * this._x;\r\n\t\t\t\tthis._y = s * y + t * this._y;\r\n\t\t\t\tthis._z = s * z + t * this._z;\r\n\r\n\t\t\t\tthis.normalize();\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar sinHalfTheta = Math.sqrt( sqrSinHalfTheta );\r\n\t\t\tvar halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );\r\n\t\t\tvar ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,\r\n\t\t\t\tratioB = Math.sin( t * halfTheta ) / sinHalfTheta;\r\n\r\n\t\t\tthis._w = ( w * ratioA + this._w * ratioB );\r\n\t\t\tthis._x = ( x * ratioA + this._x * ratioB );\r\n\t\t\tthis._y = ( y * ratioA + this._y * ratioB );\r\n\t\t\tthis._z = ( z * ratioA + this._z * ratioB );\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( quaternion ) {\r\n\r\n\t\t\treturn ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis._x = array[ offset ];\r\n\t\t\tthis._y = array[ offset + 1 ];\r\n\t\t\tthis._z = array[ offset + 2 ];\r\n\t\t\tthis._w = array[ offset + 3 ];\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this._x;\r\n\t\t\tarray[ offset + 1 ] = this._y;\r\n\t\t\tarray[ offset + 2 ] = this._z;\r\n\t\t\tarray[ offset + 3 ] = this._w;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\t_onChange: function ( callback ) {\r\n\r\n\t\t\tthis._onChangeCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t_onChangeCallback: function () {}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author kile / http://kile.stravaganza.org/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _vector = new Vector3();\r\n\tvar _quaternion = new Quaternion();\r\n\r\n\tfunction Vector3( x, y, z ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\t\tthis.z = z || 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Vector3.prototype, {\r\n\r\n\t\tisVector3: true,\r\n\r\n\t\tset: function ( x, y, z ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\t\t\tthis.z = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( z ) {\r\n\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tcase 2: this.z = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tcase 2: return this.z;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y, this.z );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\t\t\tthis.z = v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\t\t\tthis.z += v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\t\t\tthis.z += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\t\t\tthis.z = a.z + b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\t\t\tthis.z += v.z * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\t\t\tthis.z -= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\t\t\tthis.z -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\t\t\tthis.z = a.z - b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x *= v.x;\r\n\t\t\tthis.y *= v.y;\r\n\t\t\tthis.z *= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\t\t\tthis.z *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x * b.x;\r\n\t\t\tthis.y = a.y * b.y;\r\n\t\t\tthis.z = a.z * b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyEuler: function ( euler ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.applyQuaternion( _quaternion.setFromEuler( euler ) );\r\n\r\n\t\t},\r\n\r\n\t\tapplyAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\treturn this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyNormalMatrix: function ( m ) {\r\n\r\n\t\t\treturn this.applyMatrix3( m ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tvar w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );\r\n\r\n\t\t\tthis.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;\r\n\t\t\tthis.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;\r\n\t\t\tthis.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyQuaternion: function ( q ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar qx = q.x, qy = q.y, qz = q.z, qw = q.w;\r\n\r\n\t\t\t// calculate quat * vector\r\n\r\n\t\t\tvar ix = qw * x + qy * z - qz * y;\r\n\t\t\tvar iy = qw * y + qz * x - qx * z;\r\n\t\t\tvar iz = qw * z + qx * y - qy * x;\r\n\t\t\tvar iw = - qx * x - qy * y - qz * z;\r\n\r\n\t\t\t// calculate result * inverse quat\r\n\r\n\t\t\tthis.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;\r\n\t\t\tthis.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;\r\n\t\t\tthis.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tproject: function ( camera ) {\r\n\r\n\t\t\treturn this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\tunproject: function ( camera ) {\r\n\r\n\t\t\treturn this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\ttransformDirection: function ( m ) {\r\n\r\n\t\t\t// input: THREE.Matrix4 affine matrix\r\n\t\t\t// vector interpreted as a direction\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;\r\n\r\n\t\t\treturn this.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tdivide: function ( v ) {\r\n\r\n\t\t\tthis.x /= v.x;\r\n\t\t\tthis.y /= v.y;\r\n\t\t\tthis.z /= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\t\t\tthis.z = Math.min( this.z, v.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\t\t\tthis.z = Math.max( this.z, v.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\t\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\t\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\t\t\tthis.z = Math.floor( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\t\t\tthis.z = Math.ceil( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\t\t\tthis.z = Math.round( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\t\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\t\t\tthis.z = - this.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\r\n\r\n\t\t},\r\n\r\n\t\t// TODO lengthSquared?\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y + this.z * this.z;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\t\t\tthis.z += ( v.z - this.z ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tcross: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.crossVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.crossVectors( this, v );\r\n\r\n\t\t},\r\n\r\n\t\tcrossVectors: function ( a, b ) {\r\n\r\n\t\t\tvar ax = a.x, ay = a.y, az = a.z;\r\n\t\t\tvar bx = b.x, by = b.y, bz = b.z;\r\n\r\n\t\t\tthis.x = ay * bz - az * by;\r\n\t\t\tthis.y = az * bx - ax * bz;\r\n\t\t\tthis.z = ax * by - ay * bx;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tprojectOnVector: function ( v ) {\r\n\r\n\t\t\t// v cannot be the zero v\r\n\r\n\t\t\tvar scalar = v.dot( this ) / v.lengthSq();\r\n\r\n\t\t\treturn this.copy( v ).multiplyScalar( scalar );\r\n\r\n\t\t},\r\n\r\n\t\tprojectOnPlane: function ( planeNormal ) {\r\n\r\n\t\t\t_vector.copy( this ).projectOnVector( planeNormal );\r\n\r\n\t\t\treturn this.sub( _vector );\r\n\r\n\t\t},\r\n\r\n\t\treflect: function ( normal ) {\r\n\r\n\t\t\t// reflect incident vector off plane orthogonal to normal\r\n\t\t\t// normal is assumed to have unit length\r\n\r\n\t\t\treturn this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tangleTo: function ( v ) {\r\n\r\n\t\t\tvar denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );\r\n\r\n\t\t\tif ( denominator === 0 ) { console.error( 'THREE.Vector3: angleTo() can\\'t handle zero length vectors.' ); }\r\n\r\n\t\t\tvar theta = this.dot( v ) / denominator;\r\n\r\n\t\t\t// clamp, to handle numerical problems\r\n\r\n\t\t\treturn Math.acos( _Math.clamp( theta, - 1, 1 ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceToSquared( v ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSquared: function ( v ) {\r\n\r\n\t\t\tvar dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\r\n\r\n\t\t\treturn dx * dx + dy * dy + dz * dz;\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanDistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromSpherical: function ( s ) {\r\n\r\n\t\t\treturn this.setFromSphericalCoords( s.radius, s.phi, s.theta );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromSphericalCoords: function ( radius, phi, theta ) {\r\n\r\n\t\t\tvar sinPhiRadius = Math.sin( phi ) * radius;\r\n\r\n\t\t\tthis.x = sinPhiRadius * Math.sin( theta );\r\n\t\t\tthis.y = Math.cos( phi ) * radius;\r\n\t\t\tthis.z = sinPhiRadius * Math.cos( theta );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCylindrical: function ( c ) {\r\n\r\n\t\t\treturn this.setFromCylindricalCoords( c.radius, c.theta, c.y );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCylindricalCoords: function ( radius, theta, y ) {\r\n\r\n\t\t\tthis.x = radius * Math.sin( theta );\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = radius * Math.cos( theta );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixPosition: function ( m ) {\r\n\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 12 ];\r\n\t\t\tthis.y = e[ 13 ];\r\n\t\t\tthis.z = e[ 14 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixScale: function ( m ) {\r\n\r\n\t\t\tvar sx = this.setFromMatrixColumn( m, 0 ).length();\r\n\t\t\tvar sy = this.setFromMatrixColumn( m, 1 ).length();\r\n\t\t\tvar sz = this.setFromMatrixColumn( m, 2 ).length();\r\n\r\n\t\t\tthis.x = sx;\r\n\t\t\tthis.y = sy;\r\n\t\t\tthis.z = sz;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixColumn: function ( m, index ) {\r\n\r\n\t\t\treturn this.fromArray( m.elements, index * 4 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\t\t\tthis.z = array[ offset + 2 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\t\t\tarray[ offset + 2 ] = this.z;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\t\t\tthis.z = attribute.getZ( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t * @author tschw\r\n\t */\r\n\r\n\tvar _vector$1 = new Vector3();\r\n\r\n\tfunction Matrix3() {\r\n\r\n\t\tthis.elements = [\r\n\r\n\t\t\t1, 0, 0,\r\n\t\t\t0, 1, 0,\r\n\t\t\t0, 0, 1\r\n\r\n\t\t];\r\n\r\n\t\tif ( arguments.length > 0 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Matrix3.prototype, {\r\n\r\n\t\tisMatrix3: true,\r\n\r\n\t\tset: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;\r\n\t\t\tte[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;\r\n\t\t\tte[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tidentity: function () {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0,\r\n\t\t\t\t0, 1, 0,\r\n\t\t\t\t0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().fromArray( this.elements );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];\r\n\t\t\tte[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];\r\n\t\t\tte[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrix4: function ( m ) {\r\n\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tme[ 0 ], me[ 4 ], me[ 8 ],\r\n\t\t\t\tme[ 1 ], me[ 5 ], me[ 9 ],\r\n\t\t\t\tme[ 2 ], me[ 6 ], me[ 10 ]\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyToBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$1.x = attribute.getX( i );\r\n\t\t\t\t_vector$1.y = attribute.getY( i );\r\n\t\t\t\t_vector$1.z = attribute.getZ( i );\r\n\r\n\t\t\t\t_vector$1.applyMatrix3( this );\r\n\r\n\t\t\t\tattribute.setXYZ( i, _vector$1.x, _vector$1.y, _vector$1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn attribute;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( this, m );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( m, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyMatrices: function ( a, b ) {\r\n\r\n\t\t\tvar ae = a.elements;\r\n\t\t\tvar be = b.elements;\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];\r\n\t\t\tvar a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];\r\n\t\t\tvar a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];\r\n\r\n\t\t\tvar b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];\r\n\t\t\tvar b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];\r\n\t\t\tvar b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];\r\n\r\n\t\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;\r\n\t\t\tte[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;\r\n\t\t\tte[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;\r\n\r\n\t\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;\r\n\t\t\tte[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;\r\n\t\t\tte[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;\r\n\r\n\t\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;\r\n\t\t\tte[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;\r\n\t\t\tte[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;\r\n\t\t\tte[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;\r\n\t\t\tte[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdeterminant: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],\r\n\t\t\t\td = te[ 3 ], e = te[ 4 ], f = te[ 5 ],\r\n\t\t\t\tg = te[ 6 ], h = te[ 7 ], i = te[ 8 ];\r\n\r\n\t\t\treturn a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;\r\n\r\n\t\t},\r\n\r\n\t\tgetInverse: function ( matrix, throwOnDegenerate ) {\r\n\r\n\t\t\tif ( matrix && matrix.isMatrix4 ) {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument.\" );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar me = matrix.elements,\r\n\t\t\t\tte = this.elements,\r\n\r\n\t\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],\r\n\t\t\t\tn12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],\r\n\t\t\t\tn13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],\r\n\r\n\t\t\t\tt11 = n33 * n22 - n32 * n23,\r\n\t\t\t\tt12 = n32 * n13 - n33 * n12,\r\n\t\t\t\tt13 = n23 * n12 - n22 * n13,\r\n\r\n\t\t\t\tdet = n11 * t11 + n21 * t12 + n31 * t13;\r\n\r\n\t\t\tif ( det === 0 ) {\r\n\r\n\t\t\t\tvar msg = \"THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0\";\r\n\r\n\t\t\t\tif ( throwOnDegenerate === true ) {\r\n\r\n\t\t\t\t\tthrow new Error( msg );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( msg );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this.identity();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar detInv = 1 / det;\r\n\r\n\t\t\tte[ 0 ] = t11 * detInv;\r\n\t\t\tte[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;\r\n\t\t\tte[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;\r\n\r\n\t\t\tte[ 3 ] = t12 * detInv;\r\n\t\t\tte[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;\r\n\t\t\tte[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;\r\n\r\n\t\t\tte[ 6 ] = t13 * detInv;\r\n\t\t\tte[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;\r\n\t\t\tte[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranspose: function () {\r\n\r\n\t\t\tvar tmp, m = this.elements;\r\n\r\n\t\t\ttmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;\r\n\t\t\ttmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;\r\n\t\t\ttmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetNormalMatrix: function ( matrix4 ) {\r\n\r\n\t\t\treturn this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();\r\n\r\n\t\t},\r\n\r\n\t\ttransposeIntoArray: function ( r ) {\r\n\r\n\t\t\tvar m = this.elements;\r\n\r\n\t\t\tr[ 0 ] = m[ 0 ];\r\n\t\t\tr[ 1 ] = m[ 3 ];\r\n\t\t\tr[ 2 ] = m[ 6 ];\r\n\t\t\tr[ 3 ] = m[ 1 ];\r\n\t\t\tr[ 4 ] = m[ 4 ];\r\n\t\t\tr[ 5 ] = m[ 7 ];\r\n\t\t\tr[ 6 ] = m[ 2 ];\r\n\t\t\tr[ 7 ] = m[ 5 ];\r\n\t\t\tr[ 8 ] = m[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {\r\n\r\n\t\t\tvar c = Math.cos( rotation );\r\n\t\t\tvar s = Math.sin( rotation );\r\n\r\n\t\t\tthis.set(\r\n\t\t\t\tsx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,\r\n\t\t\t\t- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,\r\n\t\t\t\t0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( sx, sy ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;\r\n\t\t\tte[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotate: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta );\r\n\t\t\tvar s = Math.sin( theta );\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];\r\n\t\t\tvar a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];\r\n\r\n\t\t\tte[ 0 ] = c * a11 + s * a21;\r\n\t\t\tte[ 3 ] = c * a12 + s * a22;\r\n\t\t\tte[ 6 ] = c * a13 + s * a23;\r\n\r\n\t\t\tte[ 1 ] = - s * a11 + c * a21;\r\n\t\t\tte[ 4 ] = - s * a12 + c * a22;\r\n\t\t\tte[ 7 ] = - s * a13 + c * a23;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( tx, ty ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];\r\n\t\t\tte[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( matrix ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = matrix.elements;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tif ( te[ i ] !== me[ i ] ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.elements[ i ] = array[ i + offset ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tarray[ offset ] = te[ 0 ];\r\n\t\t\tarray[ offset + 1 ] = te[ 1 ];\r\n\t\t\tarray[ offset + 2 ] = te[ 2 ];\r\n\r\n\t\t\tarray[ offset + 3 ] = te[ 3 ];\r\n\t\t\tarray[ offset + 4 ] = te[ 4 ];\r\n\t\t\tarray[ offset + 5 ] = te[ 5 ];\r\n\r\n\t\t\tarray[ offset + 6 ] = te[ 6 ];\r\n\t\t\tarray[ offset + 7 ] = te[ 7 ];\r\n\t\t\tarray[ offset + 8 ] = te[ 8 ];\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t */\r\n\r\n\tvar _canvas;\r\n\r\n\tvar ImageUtils = {\r\n\r\n\t\tgetDataURL: function ( image ) {\r\n\r\n\t\t\tvar canvas;\r\n\r\n\t\t\tif ( typeof HTMLCanvasElement == 'undefined' ) {\r\n\r\n\t\t\t\treturn image.src;\r\n\r\n\t\t\t} else if ( image instanceof HTMLCanvasElement ) {\r\n\r\n\t\t\t\tcanvas = image;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( _canvas === undefined ) { _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); }\r\n\r\n\t\t\t\t_canvas.width = image.width;\r\n\t\t\t\t_canvas.height = image.height;\r\n\r\n\t\t\t\tvar context = _canvas.getContext( '2d' );\r\n\r\n\t\t\t\tif ( image instanceof ImageData ) {\r\n\r\n\t\t\t\t\tcontext.putImageData( image, 0, 0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tcontext.drawImage( image, 0, 0, image.width, image.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcanvas = _canvas;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( canvas.width > 2048 || canvas.height > 2048 ) {\r\n\r\n\t\t\t\treturn canvas.toDataURL( 'image/jpeg', 0.6 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn canvas.toDataURL( 'image/png' );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t */\r\n\r\n\tvar textureId = 0;\r\n\r\n\tfunction Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: textureId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;\r\n\t\tthis.mipmaps = [];\r\n\r\n\t\tthis.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;\r\n\r\n\t\tthis.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;\r\n\t\tthis.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;\r\n\r\n\t\tthis.anisotropy = anisotropy !== undefined ? anisotropy : 1;\r\n\r\n\t\tthis.format = format !== undefined ? format : RGBAFormat;\r\n\t\tthis.type = type !== undefined ? type : UnsignedByteType;\r\n\r\n\t\tthis.offset = new Vector2( 0, 0 );\r\n\t\tthis.repeat = new Vector2( 1, 1 );\r\n\t\tthis.center = new Vector2( 0, 0 );\r\n\t\tthis.rotation = 0;\r\n\r\n\t\tthis.matrixAutoUpdate = true;\r\n\t\tthis.matrix = new Matrix3();\r\n\r\n\t\tthis.generateMipmaps = true;\r\n\t\tthis.premultiplyAlpha = false;\r\n\t\tthis.flipY = true;\r\n\t\tthis.unpackAlignment = 4;\t// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)\r\n\r\n\t\t// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.\r\n\t\t//\r\n\t\t// Also changing the encoding after already used by a Material will not automatically make the Material\r\n\t\t// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.\r\n\t\tthis.encoding = encoding !== undefined ? encoding : LinearEncoding;\r\n\r\n\t\tthis.version = 0;\r\n\t\tthis.onUpdate = null;\r\n\r\n\t}\r\n\r\n\tTexture.DEFAULT_IMAGE = undefined;\r\n\tTexture.DEFAULT_MAPPING = UVMapping;\r\n\r\n\tTexture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Texture,\r\n\r\n\t\tisTexture: true,\r\n\r\n\t\tupdateMatrix: function () {\r\n\r\n\t\t\tthis.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.image = source.image;\r\n\t\t\tthis.mipmaps = source.mipmaps.slice( 0 );\r\n\r\n\t\t\tthis.mapping = source.mapping;\r\n\r\n\t\t\tthis.wrapS = source.wrapS;\r\n\t\t\tthis.wrapT = source.wrapT;\r\n\r\n\t\t\tthis.magFilter = source.magFilter;\r\n\t\t\tthis.minFilter = source.minFilter;\r\n\r\n\t\t\tthis.anisotropy = source.anisotropy;\r\n\r\n\t\t\tthis.format = source.format;\r\n\t\t\tthis.type = source.type;\r\n\r\n\t\t\tthis.offset.copy( source.offset );\r\n\t\t\tthis.repeat.copy( source.repeat );\r\n\t\t\tthis.center.copy( source.center );\r\n\t\t\tthis.rotation = source.rotation;\r\n\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\t\t\tthis.matrix.copy( source.matrix );\r\n\r\n\t\t\tthis.generateMipmaps = source.generateMipmaps;\r\n\t\t\tthis.premultiplyAlpha = source.premultiplyAlpha;\r\n\t\t\tthis.flipY = source.flipY;\r\n\t\t\tthis.unpackAlignment = source.unpackAlignment;\r\n\t\t\tthis.encoding = source.encoding;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tif ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {\r\n\r\n\t\t\t\treturn meta.textures[ this.uuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar output = {\r\n\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Texture',\r\n\t\t\t\t\tgenerator: 'Texture.toJSON'\r\n\t\t\t\t},\r\n\r\n\t\t\t\tuuid: this.uuid,\r\n\t\t\t\tname: this.name,\r\n\r\n\t\t\t\tmapping: this.mapping,\r\n\r\n\t\t\t\trepeat: [ this.repeat.x, this.repeat.y ],\r\n\t\t\t\toffset: [ this.offset.x, this.offset.y ],\r\n\t\t\t\tcenter: [ this.center.x, this.center.y ],\r\n\t\t\t\trotation: this.rotation,\r\n\r\n\t\t\t\twrap: [ this.wrapS, this.wrapT ],\r\n\r\n\t\t\t\tformat: this.format,\r\n\t\t\t\ttype: this.type,\r\n\t\t\t\tencoding: this.encoding,\r\n\r\n\t\t\t\tminFilter: this.minFilter,\r\n\t\t\t\tmagFilter: this.magFilter,\r\n\t\t\t\tanisotropy: this.anisotropy,\r\n\r\n\t\t\t\tflipY: this.flipY,\r\n\r\n\t\t\t\tpremultiplyAlpha: this.premultiplyAlpha,\r\n\t\t\t\tunpackAlignment: this.unpackAlignment\r\n\r\n\t\t\t};\r\n\r\n\t\t\tif ( this.image !== undefined ) {\r\n\r\n\t\t\t\t// TODO: Move to THREE.Image\r\n\r\n\t\t\t\tvar image = this.image;\r\n\r\n\t\t\t\tif ( image.uuid === undefined ) {\r\n\r\n\t\t\t\t\timage.uuid = _Math.generateUUID(); // UGH\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\tvar url;\r\n\r\n\t\t\t\t\tif ( Array.isArray( image ) ) {\r\n\r\n\t\t\t\t\t\t// process array of images e.g. CubeTexture\r\n\r\n\t\t\t\t\t\turl = [];\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, l = image.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\turl.push( ImageUtils.getDataURL( image[ i ] ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// process single image\r\n\r\n\t\t\t\t\t\turl = ImageUtils.getDataURL( image );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmeta.images[ image.uuid ] = {\r\n\t\t\t\t\t\tuuid: image.uuid,\r\n\t\t\t\t\t\turl: url\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\toutput.image = image.uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! isRootObject ) {\r\n\r\n\t\t\t\tmeta.textures[ this.uuid ] = output;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t},\r\n\r\n\t\ttransformUv: function ( uv ) {\r\n\r\n\t\t\tif ( this.mapping !== UVMapping ) { return uv; }\r\n\r\n\t\t\tuv.applyMatrix3( this.matrix );\r\n\r\n\t\t\tif ( uv.x < 0 || uv.x > 1 ) {\r\n\r\n\t\t\t\tswitch ( this.wrapS ) {\r\n\r\n\t\t\t\t\tcase RepeatWrapping:\r\n\r\n\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase ClampToEdgeWrapping:\r\n\r\n\t\t\t\t\t\tuv.x = uv.x < 0 ? 0 : 1;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase MirroredRepeatWrapping:\r\n\r\n\t\t\t\t\t\tif ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {\r\n\r\n\t\t\t\t\t\t\tuv.x = Math.ceil( uv.x ) - uv.x;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv.y < 0 || uv.y > 1 ) {\r\n\r\n\t\t\t\tswitch ( this.wrapT ) {\r\n\r\n\t\t\t\t\tcase RepeatWrapping:\r\n\r\n\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase ClampToEdgeWrapping:\r\n\r\n\t\t\t\t\t\tuv.y = uv.y < 0 ? 0 : 1;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase MirroredRepeatWrapping:\r\n\r\n\t\t\t\t\t\tif ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {\r\n\r\n\t\t\t\t\t\t\tuv.y = Math.ceil( uv.y ) - uv.y;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.flipY ) {\r\n\r\n\t\t\t\tuv.y = 1 - uv.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn uv;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Texture.prototype, \"needsUpdate\", {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Vector4( x, y, z, w ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\t\tthis.z = z || 0;\r\n\t\tthis.w = ( w !== undefined ) ? w : 1;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( Vector4.prototype, {\r\n\r\n\t\t\"width\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.z = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t\"height\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.w;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.w = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector4.prototype, {\r\n\r\n\t\tisVector4: true,\r\n\r\n\t\tset: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = z;\r\n\t\t\tthis.w = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\t\t\tthis.z = scalar;\r\n\t\t\tthis.w = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( z ) {\r\n\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( w ) {\r\n\r\n\t\t\tthis.w = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tcase 2: this.z = value; break;\r\n\t\t\t\tcase 3: this.w = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tcase 2: return this.z;\r\n\t\t\t\tcase 3: return this.w;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y, this.z, this.w );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\t\t\tthis.z = v.z;\r\n\t\t\tthis.w = ( v.w !== undefined ) ? v.w : 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\t\t\tthis.z += v.z;\r\n\t\t\tthis.w += v.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\t\t\tthis.z += s;\r\n\t\t\tthis.w += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\t\t\tthis.z = a.z + b.z;\r\n\t\t\tthis.w = a.w + b.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\t\t\tthis.z += v.z * s;\r\n\t\t\tthis.w += v.w * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\t\t\tthis.z -= v.z;\r\n\t\t\tthis.w -= v.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\t\t\tthis.z -= s;\r\n\t\t\tthis.w -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\t\t\tthis.z = a.z - b.z;\r\n\t\t\tthis.w = a.w - b.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\t\t\tthis.z *= scalar;\r\n\t\t\tthis.w *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z, w = this.w;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;\r\n\t\t\tthis.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tsetAxisAngleFromQuaternion: function ( q ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\r\n\r\n\t\t\t// q is assumed to be normalized\r\n\r\n\t\t\tthis.w = 2 * Math.acos( q.w );\r\n\r\n\t\t\tvar s = Math.sqrt( 1 - q.w * q.w );\r\n\r\n\t\t\tif ( s < 0.0001 ) {\r\n\r\n\t\t\t\tthis.x = 1;\r\n\t\t\t\tthis.y = 0;\r\n\t\t\t\tthis.z = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.x = q.x / s;\r\n\t\t\t\tthis.y = q.y / s;\r\n\t\t\t\tthis.z = q.z / s;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetAxisAngleFromRotationMatrix: function ( m ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar angle, x, y, z,\t\t// variables for result\r\n\t\t\t\tepsilon = 0.01,\t\t// margin to allow for rounding errors\r\n\t\t\t\tepsilon2 = 0.1,\t\t// margin to distinguish between 0 and 180 degrees\r\n\r\n\t\t\t\tte = m.elements,\r\n\r\n\t\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\r\n\t\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\r\n\t\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\r\n\r\n\t\t\tif ( ( Math.abs( m12 - m21 ) < epsilon ) &&\r\n\t\t\t ( Math.abs( m13 - m31 ) < epsilon ) &&\r\n\t\t\t ( Math.abs( m23 - m32 ) < epsilon ) ) {\r\n\r\n\t\t\t\t// singularity found\r\n\t\t\t\t// first check for identity matrix which must have +1 for all terms\r\n\t\t\t\t// in leading diagonal and zero in other terms\r\n\r\n\t\t\t\tif ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m13 + m31 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m23 + m32 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {\r\n\r\n\t\t\t\t\t// this singularity is identity matrix so angle = 0\r\n\r\n\t\t\t\t\tthis.set( 1, 0, 0, 0 );\r\n\r\n\t\t\t\t\treturn this; // zero angle, arbitrary axis\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// otherwise this singularity is angle = 180\r\n\r\n\t\t\t\tangle = Math.PI;\r\n\r\n\t\t\t\tvar xx = ( m11 + 1 ) / 2;\r\n\t\t\t\tvar yy = ( m22 + 1 ) / 2;\r\n\t\t\t\tvar zz = ( m33 + 1 ) / 2;\r\n\t\t\t\tvar xy = ( m12 + m21 ) / 4;\r\n\t\t\t\tvar xz = ( m13 + m31 ) / 4;\r\n\t\t\t\tvar yz = ( m23 + m32 ) / 4;\r\n\r\n\t\t\t\tif ( ( xx > yy ) && ( xx > zz ) ) {\r\n\r\n\t\t\t\t\t// m11 is the largest diagonal term\r\n\r\n\t\t\t\t\tif ( xx < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0;\r\n\t\t\t\t\t\ty = 0.707106781;\r\n\t\t\t\t\t\tz = 0.707106781;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tx = Math.sqrt( xx );\r\n\t\t\t\t\t\ty = xy / x;\r\n\t\t\t\t\t\tz = xz / x;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( yy > zz ) {\r\n\r\n\t\t\t\t\t// m22 is the largest diagonal term\r\n\r\n\t\t\t\t\tif ( yy < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0.707106781;\r\n\t\t\t\t\t\ty = 0;\r\n\t\t\t\t\t\tz = 0.707106781;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ty = Math.sqrt( yy );\r\n\t\t\t\t\t\tx = xy / y;\r\n\t\t\t\t\t\tz = yz / y;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// m33 is the largest diagonal term so base result on this\r\n\r\n\t\t\t\t\tif ( zz < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0.707106781;\r\n\t\t\t\t\t\ty = 0.707106781;\r\n\t\t\t\t\t\tz = 0;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tz = Math.sqrt( zz );\r\n\t\t\t\t\t\tx = xz / z;\r\n\t\t\t\t\t\ty = yz / z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.set( x, y, z, angle );\r\n\r\n\t\t\t\treturn this; // return 180 deg rotation\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// as we have reached here there are no singularities so we can handle normally\r\n\r\n\t\t\tvar s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +\r\n\t\t\t ( m13 - m31 ) * ( m13 - m31 ) +\r\n\t\t\t ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize\r\n\r\n\t\t\tif ( Math.abs( s ) < 0.001 ) { s = 1; }\r\n\r\n\t\t\t// prevent divide by zero, should not happen if matrix is orthogonal and should be\r\n\t\t\t// caught by singularity test above, but I've left it in just in case\r\n\r\n\t\t\tthis.x = ( m32 - m23 ) / s;\r\n\t\t\tthis.y = ( m13 - m31 ) / s;\r\n\t\t\tthis.z = ( m21 - m12 ) / s;\r\n\t\t\tthis.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\t\t\tthis.z = Math.min( this.z, v.z );\r\n\t\t\tthis.w = Math.min( this.w, v.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\t\t\tthis.z = Math.max( this.z, v.z );\r\n\t\t\tthis.w = Math.max( this.w, v.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\t\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\r\n\t\t\tthis.w = Math.max( min.w, Math.min( max.w, this.w ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\t\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\r\n\t\t\tthis.w = Math.max( minVal, Math.min( maxVal, this.w ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\t\t\tthis.z = Math.floor( this.z );\r\n\t\t\tthis.w = Math.floor( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\t\t\tthis.z = Math.ceil( this.z );\r\n\t\t\tthis.w = Math.ceil( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\t\t\tthis.z = Math.round( this.z );\r\n\t\t\tthis.w = Math.round( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\t\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\r\n\t\t\tthis.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\t\t\tthis.z = - this.z;\r\n\t\t\tthis.w = - this.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\t\t\tthis.z += ( v.z - this.z ) * alpha;\r\n\t\t\tthis.w += ( v.w - this.w ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\t\t\tthis.z = array[ offset + 2 ];\r\n\t\t\tthis.w = array[ offset + 3 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\t\t\tarray[ offset + 2 ] = this.z;\r\n\t\t\tarray[ offset + 3 ] = this.w;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\t\t\tthis.z = attribute.getZ( index );\r\n\t\t\tthis.w = attribute.getW( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author szimek / https://github.com/szimek/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author Marius Kintel / https://github.com/kintel\r\n\t */\r\n\r\n\t/*\r\n\t In options, we can specify:\r\n\t * Texture parameters for an auto-generated target texture\r\n\t * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers\r\n\t*/\r\n\tfunction WebGLRenderTarget( width, height, options ) {\r\n\r\n\t\tthis.width = width;\r\n\t\tthis.height = height;\r\n\r\n\t\tthis.scissor = new Vector4( 0, 0, width, height );\r\n\t\tthis.scissorTest = false;\r\n\r\n\t\tthis.viewport = new Vector4( 0, 0, width, height );\r\n\r\n\t\toptions = options || {};\r\n\r\n\t\tthis.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );\r\n\r\n\t\tthis.texture.image = {};\r\n\t\tthis.texture.image.width = width;\r\n\t\tthis.texture.image.height = height;\r\n\r\n\t\tthis.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;\r\n\t\tthis.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;\r\n\r\n\t\tthis.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;\r\n\t\tthis.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;\r\n\t\tthis.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;\r\n\r\n\t}\r\n\r\n\tWebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: WebGLRenderTarget,\r\n\r\n\t\tisWebGLRenderTarget: true,\r\n\r\n\t\tsetSize: function ( width, height ) {\r\n\r\n\t\t\tif ( this.width !== width || this.height !== height ) {\r\n\r\n\t\t\t\tthis.width = width;\r\n\t\t\t\tthis.height = height;\r\n\r\n\t\t\t\tthis.texture.image.width = width;\r\n\t\t\t\tthis.texture.image.height = height;\r\n\r\n\t\t\t\tthis.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.viewport.set( 0, 0, width, height );\r\n\t\t\tthis.scissor.set( 0, 0, width, height );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.width = source.width;\r\n\t\t\tthis.height = source.height;\r\n\r\n\t\t\tthis.viewport.copy( source.viewport );\r\n\r\n\t\t\tthis.texture = source.texture.clone();\r\n\r\n\t\t\tthis.depthBuffer = source.depthBuffer;\r\n\t\t\tthis.stencilBuffer = source.stencilBuffer;\r\n\t\t\tthis.depthTexture = source.depthTexture;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author Matt DesLauriers / @mattdesl\r\n\t */\r\n\r\n\tfunction WebGLMultisampleRenderTarget( width, height, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t\tthis.samples = 4;\r\n\r\n\t}\r\n\r\n\tWebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {\r\n\r\n\t\tconstructor: WebGLMultisampleRenderTarget,\r\n\r\n\t\tisWebGLMultisampleRenderTarget: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tWebGLRenderTarget.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.samples = source.samples;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _v1 = new Vector3();\r\n\tvar _m1 = new Matrix4();\r\n\tvar _zero = new Vector3( 0, 0, 0 );\r\n\tvar _one = new Vector3( 1, 1, 1 );\r\n\tvar _x = new Vector3();\r\n\tvar _y = new Vector3();\r\n\tvar _z = new Vector3();\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author jordi_ros / http://plattsoft.com\r\n\t * @author D1plo1d / http://github.com/D1plo1d\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author timknip / http://www.floorplanner.com/\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Matrix4() {\r\n\r\n\t\tthis.elements = [\r\n\r\n\t\t\t1, 0, 0, 0,\r\n\t\t\t0, 1, 0, 0,\r\n\t\t\t0, 0, 1, 0,\r\n\t\t\t0, 0, 0, 1\r\n\r\n\t\t];\r\n\r\n\t\tif ( arguments.length > 0 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Matrix4.prototype, {\r\n\r\n\t\tisMatrix4: true,\r\n\r\n\t\tset: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;\r\n\t\t\tte[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;\r\n\t\t\tte[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;\r\n\t\t\tte[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tidentity: function () {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, 0,\r\n\t\t\t\t0, 1, 0, 0,\r\n\t\t\t\t0, 0, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Matrix4().fromArray( this.elements );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];\r\n\t\t\tte[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];\r\n\t\t\tte[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];\r\n\t\t\tte[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyPosition: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements, me = m.elements;\r\n\r\n\t\t\tte[ 12 ] = me[ 12 ];\r\n\t\t\tte[ 13 ] = me[ 13 ];\r\n\t\t\tte[ 14 ] = me[ 14 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\textractBasis: function ( xAxis, yAxis, zAxis ) {\r\n\r\n\t\t\txAxis.setFromMatrixColumn( this, 0 );\r\n\t\t\tyAxis.setFromMatrixColumn( this, 1 );\r\n\t\t\tzAxis.setFromMatrixColumn( this, 2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeBasis: function ( xAxis, yAxis, zAxis ) {\r\n\r\n\t\t\tthis.set(\r\n\t\t\t\txAxis.x, yAxis.x, zAxis.x, 0,\r\n\t\t\t\txAxis.y, yAxis.y, zAxis.y, 0,\r\n\t\t\t\txAxis.z, yAxis.z, zAxis.z, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\textractRotation: function ( m ) {\r\n\r\n\t\t\t// this method does not support reflection matrices\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tvar scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();\r\n\t\t\tvar scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();\r\n\t\t\tvar scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ] * scaleX;\r\n\t\t\tte[ 1 ] = me[ 1 ] * scaleX;\r\n\t\t\tte[ 2 ] = me[ 2 ] * scaleX;\r\n\t\t\tte[ 3 ] = 0;\r\n\r\n\t\t\tte[ 4 ] = me[ 4 ] * scaleY;\r\n\t\t\tte[ 5 ] = me[ 5 ] * scaleY;\r\n\t\t\tte[ 6 ] = me[ 6 ] * scaleY;\r\n\t\t\tte[ 7 ] = 0;\r\n\r\n\t\t\tte[ 8 ] = me[ 8 ] * scaleZ;\r\n\t\t\tte[ 9 ] = me[ 9 ] * scaleZ;\r\n\t\t\tte[ 10 ] = me[ 10 ] * scaleZ;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\tte[ 12 ] = 0;\r\n\t\t\tte[ 13 ] = 0;\r\n\t\t\tte[ 14 ] = 0;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationFromEuler: function ( euler ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar x = euler.x, y = euler.y, z = euler.z;\r\n\t\t\tvar a = Math.cos( x ), b = Math.sin( x );\r\n\t\t\tvar c = Math.cos( y ), d = Math.sin( y );\r\n\t\t\tvar e = Math.cos( z ), f = Math.sin( z );\r\n\r\n\t\t\tif ( euler.order === 'XYZ' ) {\r\n\r\n\t\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = - c * f;\r\n\t\t\t\tte[ 8 ] = d;\r\n\r\n\t\t\t\tte[ 1 ] = af + be * d;\r\n\t\t\t\tte[ 5 ] = ae - bf * d;\r\n\t\t\t\tte[ 9 ] = - b * c;\r\n\r\n\t\t\t\tte[ 2 ] = bf - ae * d;\r\n\t\t\t\tte[ 6 ] = be + af * d;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'YXZ' ) {\r\n\r\n\t\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\r\n\r\n\t\t\t\tte[ 0 ] = ce + df * b;\r\n\t\t\t\tte[ 4 ] = de * b - cf;\r\n\t\t\t\tte[ 8 ] = a * d;\r\n\r\n\t\t\t\tte[ 1 ] = a * f;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = - b;\r\n\r\n\t\t\t\tte[ 2 ] = cf * b - de;\r\n\t\t\t\tte[ 6 ] = df + ce * b;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'ZXY' ) {\r\n\r\n\t\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\r\n\r\n\t\t\t\tte[ 0 ] = ce - df * b;\r\n\t\t\t\tte[ 4 ] = - a * f;\r\n\t\t\t\tte[ 8 ] = de + cf * b;\r\n\r\n\t\t\t\tte[ 1 ] = cf + de * b;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = df - ce * b;\r\n\r\n\t\t\t\tte[ 2 ] = - a * d;\r\n\t\t\t\tte[ 6 ] = b;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'ZYX' ) {\r\n\r\n\t\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = be * d - af;\r\n\t\t\t\tte[ 8 ] = ae * d + bf;\r\n\r\n\t\t\t\tte[ 1 ] = c * f;\r\n\t\t\t\tte[ 5 ] = bf * d + ae;\r\n\t\t\t\tte[ 9 ] = af * d - be;\r\n\r\n\t\t\t\tte[ 2 ] = - d;\r\n\t\t\t\tte[ 6 ] = b * c;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'YZX' ) {\r\n\r\n\t\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = bd - ac * f;\r\n\t\t\t\tte[ 8 ] = bc * f + ad;\r\n\r\n\t\t\t\tte[ 1 ] = f;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = - b * e;\r\n\r\n\t\t\t\tte[ 2 ] = - d * e;\r\n\t\t\t\tte[ 6 ] = ad * f + bc;\r\n\t\t\t\tte[ 10 ] = ac - bd * f;\r\n\r\n\t\t\t} else if ( euler.order === 'XZY' ) {\r\n\r\n\t\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = - f;\r\n\t\t\t\tte[ 8 ] = d * e;\r\n\r\n\t\t\t\tte[ 1 ] = ac * f + bd;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = ad * f - bc;\r\n\r\n\t\t\t\tte[ 2 ] = bc * f - ad;\r\n\t\t\t\tte[ 6 ] = b * e;\r\n\t\t\t\tte[ 10 ] = bd * f + ac;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bottom row\r\n\t\t\tte[ 3 ] = 0;\r\n\t\t\tte[ 7 ] = 0;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\t// last column\r\n\t\t\tte[ 12 ] = 0;\r\n\t\t\tte[ 13 ] = 0;\r\n\t\t\tte[ 14 ] = 0;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\treturn this.compose( _zero, q, _one );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( eye, target, up ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\t_z.subVectors( eye, target );\r\n\r\n\t\t\tif ( _z.lengthSq() === 0 ) {\r\n\r\n\t\t\t\t// eye and target are in the same position\r\n\r\n\t\t\t\t_z.z = 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_z.normalize();\r\n\t\t\t_x.crossVectors( up, _z );\r\n\r\n\t\t\tif ( _x.lengthSq() === 0 ) {\r\n\r\n\t\t\t\t// up and z are parallel\r\n\r\n\t\t\t\tif ( Math.abs( up.z ) === 1 ) {\r\n\r\n\t\t\t\t\t_z.x += 0.0001;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_z.z += 0.0001;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_z.normalize();\r\n\t\t\t\t_x.crossVectors( up, _z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_x.normalize();\r\n\t\t\t_y.crossVectors( _z, _x );\r\n\r\n\t\t\tte[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;\r\n\t\t\tte[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;\r\n\t\t\tte[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( m, n ) {\r\n\r\n\t\t\tif ( n !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyMatrices( m, n );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.multiplyMatrices( this, m );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( m, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyMatrices: function ( a, b ) {\r\n\r\n\t\t\tvar ae = a.elements;\r\n\t\t\tvar be = b.elements;\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];\r\n\t\t\tvar a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];\r\n\t\t\tvar a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];\r\n\t\t\tvar a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];\r\n\r\n\t\t\tvar b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];\r\n\t\t\tvar b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];\r\n\t\t\tvar b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];\r\n\t\t\tvar b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];\r\n\r\n\t\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;\r\n\t\t\tte[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;\r\n\t\t\tte[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;\r\n\t\t\tte[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;\r\n\r\n\t\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;\r\n\t\t\tte[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;\r\n\t\t\tte[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;\r\n\t\t\tte[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;\r\n\r\n\t\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;\r\n\t\t\tte[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;\r\n\t\t\tte[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;\r\n\t\t\tte[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;\r\n\r\n\t\t\tte[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;\r\n\t\t\tte[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;\r\n\t\t\tte[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;\r\n\t\t\tte[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;\r\n\t\t\tte[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;\r\n\t\t\tte[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;\r\n\t\t\tte[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyToBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_v1.x = attribute.getX( i );\r\n\t\t\t\t_v1.y = attribute.getY( i );\r\n\t\t\t\t_v1.z = attribute.getZ( i );\r\n\r\n\t\t\t\t_v1.applyMatrix4( this );\r\n\r\n\t\t\t\tattribute.setXYZ( i, _v1.x, _v1.y, _v1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn attribute;\r\n\r\n\t\t},\r\n\r\n\t\tdeterminant: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];\r\n\t\t\tvar n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];\r\n\t\t\tvar n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];\r\n\t\t\tvar n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];\r\n\r\n\t\t\t//TODO: make this more efficient\r\n\t\t\t//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )\r\n\r\n\t\t\treturn (\r\n\t\t\t\tn41 * (\r\n\t\t\t\t\t+ n14 * n23 * n32\r\n\t\t\t\t\t - n13 * n24 * n32\r\n\t\t\t\t\t - n14 * n22 * n33\r\n\t\t\t\t\t + n12 * n24 * n33\r\n\t\t\t\t\t + n13 * n22 * n34\r\n\t\t\t\t\t - n12 * n23 * n34\r\n\t\t\t\t) +\r\n\t\t\t\tn42 * (\r\n\t\t\t\t\t+ n11 * n23 * n34\r\n\t\t\t\t\t - n11 * n24 * n33\r\n\t\t\t\t\t + n14 * n21 * n33\r\n\t\t\t\t\t - n13 * n21 * n34\r\n\t\t\t\t\t + n13 * n24 * n31\r\n\t\t\t\t\t - n14 * n23 * n31\r\n\t\t\t\t) +\r\n\t\t\t\tn43 * (\r\n\t\t\t\t\t+ n11 * n24 * n32\r\n\t\t\t\t\t - n11 * n22 * n34\r\n\t\t\t\t\t - n14 * n21 * n32\r\n\t\t\t\t\t + n12 * n21 * n34\r\n\t\t\t\t\t + n14 * n22 * n31\r\n\t\t\t\t\t - n12 * n24 * n31\r\n\t\t\t\t) +\r\n\t\t\t\tn44 * (\r\n\t\t\t\t\t- n13 * n22 * n31\r\n\t\t\t\t\t - n11 * n23 * n32\r\n\t\t\t\t\t + n11 * n22 * n33\r\n\t\t\t\t\t + n13 * n21 * n32\r\n\t\t\t\t\t - n12 * n21 * n33\r\n\t\t\t\t\t + n12 * n23 * n31\r\n\t\t\t\t)\r\n\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\ttranspose: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar tmp;\r\n\r\n\t\t\ttmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;\r\n\t\t\ttmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;\r\n\t\t\ttmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;\r\n\r\n\t\t\ttmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;\r\n\t\t\ttmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;\r\n\t\t\ttmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetPosition: function ( x, y, z ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tif ( x.isVector3 ) {\r\n\r\n\t\t\t\tte[ 12 ] = x.x;\r\n\t\t\t\tte[ 13 ] = x.y;\r\n\t\t\t\tte[ 14 ] = x.z;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tte[ 12 ] = x;\r\n\t\t\t\tte[ 13 ] = y;\r\n\t\t\t\tte[ 14 ] = z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetInverse: function ( m, throwOnDegenerate ) {\r\n\r\n\t\t\t// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm\r\n\t\t\tvar te = this.elements,\r\n\t\t\t\tme = m.elements,\r\n\r\n\t\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],\r\n\t\t\t\tn12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],\r\n\t\t\t\tn13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],\r\n\t\t\t\tn14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],\r\n\r\n\t\t\t\tt11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,\r\n\t\t\t\tt12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,\r\n\t\t\t\tt13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,\r\n\t\t\t\tt14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;\r\n\r\n\t\t\tvar det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;\r\n\r\n\t\t\tif ( det === 0 ) {\r\n\r\n\t\t\t\tvar msg = \"THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0\";\r\n\r\n\t\t\t\tif ( throwOnDegenerate === true ) {\r\n\r\n\t\t\t\t\tthrow new Error( msg );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( msg );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this.identity();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar detInv = 1 / det;\r\n\r\n\t\t\tte[ 0 ] = t11 * detInv;\r\n\t\t\tte[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;\r\n\t\t\tte[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;\r\n\t\t\tte[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 4 ] = t12 * detInv;\r\n\t\t\tte[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;\r\n\t\t\tte[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;\r\n\t\t\tte[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 8 ] = t13 * detInv;\r\n\t\t\tte[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;\r\n\t\t\tte[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;\r\n\t\t\tte[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 12 ] = t14 * detInv;\r\n\t\t\tte[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;\r\n\t\t\tte[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;\r\n\t\t\tte[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( v ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar x = v.x, y = v.y, z = v.z;\r\n\r\n\t\t\tte[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;\r\n\t\t\tte[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;\r\n\t\t\tte[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;\r\n\t\t\tte[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMaxScaleOnAxis: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];\r\n\t\t\tvar scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];\r\n\t\t\tvar scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];\r\n\r\n\t\t\treturn Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );\r\n\r\n\t\t},\r\n\r\n\t\tmakeTranslation: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, x,\r\n\t\t\t\t0, 1, 0, y,\r\n\t\t\t\t0, 0, 1, z,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationX: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, 0,\r\n\t\t\t\t0, c, - s, 0,\r\n\t\t\t\t0, s, c, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationY: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t c, 0, s, 0,\r\n\t\t\t\t 0, 1, 0, 0,\r\n\t\t\t\t- s, 0, c, 0,\r\n\t\t\t\t 0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationZ: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tc, - s, 0, 0,\r\n\t\t\t\ts, c, 0, 0,\r\n\t\t\t\t0, 0, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// Based on http://www.gamedev.net/reference/articles/article1199.asp\r\n\r\n\t\t\tvar c = Math.cos( angle );\r\n\t\t\tvar s = Math.sin( angle );\r\n\t\t\tvar t = 1 - c;\r\n\t\t\tvar x = axis.x, y = axis.y, z = axis.z;\r\n\t\t\tvar tx = t * x, ty = t * y;\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\ttx * x + c, tx * y - s * z, tx * z + s * y, 0,\r\n\t\t\t\ttx * y + s * z, ty * y + c, ty * z - s * x, 0,\r\n\t\t\t\ttx * z - s * y, ty * z + s * x, t * z * z + c, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\t return this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeScale: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tx, 0, 0, 0,\r\n\t\t\t\t0, y, 0, 0,\r\n\t\t\t\t0, 0, z, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeShear: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, y, z, 0,\r\n\t\t\t\tx, 1, z, 0,\r\n\t\t\t\tx, y, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcompose: function ( position, quaternion, scale ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;\r\n\t\t\tvar x2 = x + x,\ty2 = y + y, z2 = z + z;\r\n\t\t\tvar xx = x * x2, xy = x * y2, xz = x * z2;\r\n\t\t\tvar yy = y * y2, yz = y * z2, zz = z * z2;\r\n\t\t\tvar wx = w * x2, wy = w * y2, wz = w * z2;\r\n\r\n\t\t\tvar sx = scale.x, sy = scale.y, sz = scale.z;\r\n\r\n\t\t\tte[ 0 ] = ( 1 - ( yy + zz ) ) * sx;\r\n\t\t\tte[ 1 ] = ( xy + wz ) * sx;\r\n\t\t\tte[ 2 ] = ( xz - wy ) * sx;\r\n\t\t\tte[ 3 ] = 0;\r\n\r\n\t\t\tte[ 4 ] = ( xy - wz ) * sy;\r\n\t\t\tte[ 5 ] = ( 1 - ( xx + zz ) ) * sy;\r\n\t\t\tte[ 6 ] = ( yz + wx ) * sy;\r\n\t\t\tte[ 7 ] = 0;\r\n\r\n\t\t\tte[ 8 ] = ( xz + wy ) * sz;\r\n\t\t\tte[ 9 ] = ( yz - wx ) * sz;\r\n\t\t\tte[ 10 ] = ( 1 - ( xx + yy ) ) * sz;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\tte[ 12 ] = position.x;\r\n\t\t\tte[ 13 ] = position.y;\r\n\t\t\tte[ 14 ] = position.z;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdecompose: function ( position, quaternion, scale ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();\r\n\t\t\tvar sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();\r\n\t\t\tvar sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();\r\n\r\n\t\t\t// if determine is negative, we need to invert one scale\r\n\t\t\tvar det = this.determinant();\r\n\t\t\tif ( det < 0 ) { sx = - sx; }\r\n\r\n\t\t\tposition.x = te[ 12 ];\r\n\t\t\tposition.y = te[ 13 ];\r\n\t\t\tposition.z = te[ 14 ];\r\n\r\n\t\t\t// scale the rotation part\r\n\t\t\t_m1.copy( this );\r\n\r\n\t\t\tvar invSX = 1 / sx;\r\n\t\t\tvar invSY = 1 / sy;\r\n\t\t\tvar invSZ = 1 / sz;\r\n\r\n\t\t\t_m1.elements[ 0 ] *= invSX;\r\n\t\t\t_m1.elements[ 1 ] *= invSX;\r\n\t\t\t_m1.elements[ 2 ] *= invSX;\r\n\r\n\t\t\t_m1.elements[ 4 ] *= invSY;\r\n\t\t\t_m1.elements[ 5 ] *= invSY;\r\n\t\t\t_m1.elements[ 6 ] *= invSY;\r\n\r\n\t\t\t_m1.elements[ 8 ] *= invSZ;\r\n\t\t\t_m1.elements[ 9 ] *= invSZ;\r\n\t\t\t_m1.elements[ 10 ] *= invSZ;\r\n\r\n\t\t\tquaternion.setFromRotationMatrix( _m1 );\r\n\r\n\t\t\tscale.x = sx;\r\n\t\t\tscale.y = sy;\r\n\t\t\tscale.z = sz;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakePerspective: function ( left, right, top, bottom, near, far ) {\r\n\r\n\t\t\tif ( far === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar x = 2 * near / ( right - left );\r\n\t\t\tvar y = 2 * near / ( top - bottom );\r\n\r\n\t\t\tvar a = ( right + left ) / ( right - left );\r\n\t\t\tvar b = ( top + bottom ) / ( top - bottom );\r\n\t\t\tvar c = - ( far + near ) / ( far - near );\r\n\t\t\tvar d = - 2 * far * near / ( far - near );\r\n\r\n\t\t\tte[ 0 ] = x;\tte[ 4 ] = 0;\tte[ 8 ] = a;\tte[ 12 ] = 0;\r\n\t\t\tte[ 1 ] = 0;\tte[ 5 ] = y;\tte[ 9 ] = b;\tte[ 13 ] = 0;\r\n\t\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = c;\tte[ 14 ] = d;\r\n\t\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = - 1;\tte[ 15 ] = 0;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeOrthographic: function ( left, right, top, bottom, near, far ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar w = 1.0 / ( right - left );\r\n\t\t\tvar h = 1.0 / ( top - bottom );\r\n\t\t\tvar p = 1.0 / ( far - near );\r\n\r\n\t\t\tvar x = ( right + left ) * w;\r\n\t\t\tvar y = ( top + bottom ) * h;\r\n\t\t\tvar z = ( far + near ) * p;\r\n\r\n\t\t\tte[ 0 ] = 2 * w;\tte[ 4 ] = 0;\tte[ 8 ] = 0;\tte[ 12 ] = - x;\r\n\t\t\tte[ 1 ] = 0;\tte[ 5 ] = 2 * h;\tte[ 9 ] = 0;\tte[ 13 ] = - y;\r\n\t\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = - 2 * p;\tte[ 14 ] = - z;\r\n\t\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = 0;\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( matrix ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = matrix.elements;\r\n\r\n\t\t\tfor ( var i = 0; i < 16; i ++ ) {\r\n\r\n\t\t\t\tif ( te[ i ] !== me[ i ] ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tfor ( var i = 0; i < 16; i ++ ) {\r\n\r\n\t\t\t\tthis.elements[ i ] = array[ i + offset ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tarray[ offset ] = te[ 0 ];\r\n\t\t\tarray[ offset + 1 ] = te[ 1 ];\r\n\t\t\tarray[ offset + 2 ] = te[ 2 ];\r\n\t\t\tarray[ offset + 3 ] = te[ 3 ];\r\n\r\n\t\t\tarray[ offset + 4 ] = te[ 4 ];\r\n\t\t\tarray[ offset + 5 ] = te[ 5 ];\r\n\t\t\tarray[ offset + 6 ] = te[ 6 ];\r\n\t\t\tarray[ offset + 7 ] = te[ 7 ];\r\n\r\n\t\t\tarray[ offset + 8 ] = te[ 8 ];\r\n\t\t\tarray[ offset + 9 ] = te[ 9 ];\r\n\t\t\tarray[ offset + 10 ] = te[ 10 ];\r\n\t\t\tarray[ offset + 11 ] = te[ 11 ];\r\n\r\n\t\t\tarray[ offset + 12 ] = te[ 12 ];\r\n\t\t\tarray[ offset + 13 ] = te[ 13 ];\r\n\t\t\tarray[ offset + 14 ] = te[ 14 ];\r\n\t\t\tarray[ offset + 15 ] = te[ 15 ];\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _matrix = new Matrix4();\r\n\tvar _quaternion$1 = new Quaternion();\r\n\r\n\tfunction Euler( x, y, z, order ) {\r\n\r\n\t\tthis._x = x || 0;\r\n\t\tthis._y = y || 0;\r\n\t\tthis._z = z || 0;\r\n\t\tthis._order = order || Euler.DefaultOrder;\r\n\r\n\t}\r\n\r\n\tEuler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];\r\n\r\n\tEuler.DefaultOrder = 'XYZ';\r\n\r\n\tObject.defineProperties( Euler.prototype, {\r\n\r\n\t\tx: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._x = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ty: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._y = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tz: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._z = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\torder: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._order;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._order = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Euler.prototype, {\r\n\r\n\t\tisEuler: true,\r\n\r\n\t\tset: function ( x, y, z, order ) {\r\n\r\n\t\t\tthis._x = x;\r\n\t\t\tthis._y = y;\r\n\t\t\tthis._z = z;\r\n\t\t\tthis._order = order || this._order;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this._x, this._y, this._z, this._order );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( euler ) {\r\n\r\n\t\t\tthis._x = euler._x;\r\n\t\t\tthis._y = euler._y;\r\n\t\t\tthis._z = euler._z;\r\n\t\t\tthis._order = euler._order;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromRotationMatrix: function ( m, order, update ) {\r\n\r\n\t\t\tvar clamp = _Math.clamp;\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar te = m.elements;\r\n\t\t\tvar m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];\r\n\t\t\tvar m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];\r\n\t\t\tvar m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\r\n\r\n\t\t\torder = order || this._order;\r\n\r\n\t\t\tif ( order === 'XYZ' ) {\r\n\r\n\t\t\t\tthis._y = Math.asin( clamp( m13, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m13 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\r\n\t\t\t\t\tthis._z = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'YXZ' ) {\r\n\r\n\t\t\t\tthis._x = Math.asin( - clamp( m23, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m23 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m22 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\r\n\t\t\t\t\tthis._z = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'ZXY' ) {\r\n\r\n\t\t\t\tthis._x = Math.asin( clamp( m32, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m32 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._y = 0;\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'ZYX' ) {\r\n\r\n\t\t\t\tthis._y = Math.asin( - clamp( m31, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m31 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'YZX' ) {\r\n\r\n\t\t\t\tthis._z = Math.asin( clamp( m21, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m21 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m22 );\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'XZY' ) {\r\n\r\n\t\t\t\tthis._z = Math.asin( - clamp( m12, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m12 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\r\n\t\t\t\t\tthis._y = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._order = order;\r\n\r\n\t\t\tif ( update !== false ) { this._onChangeCallback(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromQuaternion: function ( q, order, update ) {\r\n\r\n\t\t\t_matrix.makeRotationFromQuaternion( q );\r\n\r\n\t\t\treturn this.setFromRotationMatrix( _matrix, order, update );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v, order ) {\r\n\r\n\t\t\treturn this.set( v.x, v.y, v.z, order || this._order );\r\n\r\n\t\t},\r\n\r\n\t\treorder: function ( newOrder ) {\r\n\r\n\t\t\t// WARNING: this discards revolution information -bhouston\r\n\r\n\t\t\t_quaternion$1.setFromEuler( this );\r\n\r\n\t\t\treturn this.setFromQuaternion( _quaternion$1, newOrder );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( euler ) {\r\n\r\n\t\t\treturn ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array ) {\r\n\r\n\t\t\tthis._x = array[ 0 ];\r\n\t\t\tthis._y = array[ 1 ];\r\n\t\t\tthis._z = array[ 2 ];\r\n\t\t\tif ( array[ 3 ] !== undefined ) { this._order = array[ 3 ]; }\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this._x;\r\n\t\t\tarray[ offset + 1 ] = this._y;\r\n\t\t\tarray[ offset + 2 ] = this._z;\r\n\t\t\tarray[ offset + 3 ] = this._order;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\ttoVector3: function ( optionalResult ) {\r\n\r\n\t\t\tif ( optionalResult ) {\r\n\r\n\t\t\t\treturn optionalResult.set( this._x, this._y, this._z );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn new Vector3( this._x, this._y, this._z );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_onChange: function ( callback ) {\r\n\r\n\t\t\tthis._onChangeCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t_onChangeCallback: function () {}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Layers() {\r\n\r\n\t\tthis.mask = 1 | 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Layers.prototype, {\r\n\r\n\t\tset: function ( channel ) {\r\n\r\n\t\t\tthis.mask = 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tenable: function ( channel ) {\r\n\r\n\t\t\tthis.mask |= 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tenableAll: function () {\r\n\r\n\t\t\tthis.mask = 0xffffffff | 0;\r\n\r\n\t\t},\r\n\r\n\t\ttoggle: function ( channel ) {\r\n\r\n\t\t\tthis.mask ^= 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tdisable: function ( channel ) {\r\n\r\n\t\t\tthis.mask &= ~ ( 1 << channel | 0 );\r\n\r\n\t\t},\r\n\r\n\t\tdisableAll: function () {\r\n\r\n\t\t\tthis.mask = 0;\r\n\r\n\t\t},\r\n\r\n\t\ttest: function ( layers ) {\r\n\r\n\t\t\treturn ( this.mask & layers.mask ) !== 0;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _object3DId = 0;\r\n\r\n\tvar _v1$1 = new Vector3();\r\n\tvar _q1 = new Quaternion();\r\n\tvar _m1$1 = new Matrix4();\r\n\tvar _target = new Vector3();\r\n\r\n\tvar _position = new Vector3();\r\n\tvar _scale = new Vector3();\r\n\tvar _quaternion$2 = new Quaternion();\r\n\r\n\tvar _xAxis = new Vector3( 1, 0, 0 );\r\n\tvar _yAxis = new Vector3( 0, 1, 0 );\r\n\tvar _zAxis = new Vector3( 0, 0, 1 );\r\n\r\n\tvar _addedEvent = { type: 'added' };\r\n\tvar _removedEvent = { type: 'removed' };\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author elephantatwork / www.elephantatwork.ch\r\n\t */\r\n\r\n\tfunction Object3D() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _object3DId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Object3D';\r\n\r\n\t\tthis.parent = null;\r\n\t\tthis.children = [];\r\n\r\n\t\tthis.up = Object3D.DefaultUp.clone();\r\n\r\n\t\tvar position = new Vector3();\r\n\t\tvar rotation = new Euler();\r\n\t\tvar quaternion = new Quaternion();\r\n\t\tvar scale = new Vector3( 1, 1, 1 );\r\n\r\n\t\tfunction onRotationChange() {\r\n\r\n\t\t\tquaternion.setFromEuler( rotation, false );\r\n\r\n\t\t}\r\n\r\n\t\tfunction onQuaternionChange() {\r\n\r\n\t\t\trotation.setFromQuaternion( quaternion, undefined, false );\r\n\r\n\t\t}\r\n\r\n\t\trotation._onChange( onRotationChange );\r\n\t\tquaternion._onChange( onQuaternionChange );\r\n\r\n\t\tObject.defineProperties( this, {\r\n\t\t\tposition: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: position\r\n\t\t\t},\r\n\t\t\trotation: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: rotation\r\n\t\t\t},\r\n\t\t\tquaternion: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: quaternion\r\n\t\t\t},\r\n\t\t\tscale: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: scale\r\n\t\t\t},\r\n\t\t\tmodelViewMatrix: {\r\n\t\t\t\tvalue: new Matrix4()\r\n\t\t\t},\r\n\t\t\tnormalMatrix: {\r\n\t\t\t\tvalue: new Matrix3()\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.matrix = new Matrix4();\r\n\t\tthis.matrixWorld = new Matrix4();\r\n\r\n\t\tthis.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;\r\n\t\tthis.matrixWorldNeedsUpdate = false;\r\n\r\n\t\tthis.layers = new Layers();\r\n\t\tthis.visible = true;\r\n\r\n\t\tthis.castShadow = false;\r\n\t\tthis.receiveShadow = false;\r\n\r\n\t\tthis.frustumCulled = true;\r\n\t\tthis.renderOrder = 0;\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t}\r\n\r\n\tObject3D.DefaultUp = new Vector3( 0, 1, 0 );\r\n\tObject3D.DefaultMatrixAutoUpdate = true;\r\n\r\n\tObject3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Object3D,\r\n\r\n\t\tisObject3D: true,\r\n\r\n\t\tonBeforeRender: function () {},\r\n\t\tonAfterRender: function () {},\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tthis.matrix.premultiply( matrix );\r\n\r\n\t\t\tthis.matrix.decompose( this.position, this.quaternion, this.scale );\r\n\r\n\t\t},\r\n\r\n\t\tapplyQuaternion: function ( q ) {\r\n\r\n\t\t\tthis.quaternion.premultiply( q );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\t// assumes axis is normalized\r\n\r\n\t\t\tthis.quaternion.setFromAxisAngle( axis, angle );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromEuler: function ( euler ) {\r\n\r\n\t\t\tthis.quaternion.setFromEuler( euler, true );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromMatrix: function ( m ) {\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tthis.quaternion.setFromRotationMatrix( m );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\t// assumes q is normalized\r\n\r\n\t\t\tthis.quaternion.copy( q );\r\n\r\n\t\t},\r\n\r\n\t\trotateOnAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// rotate object on axis in object space\r\n\t\t\t// axis is assumed to be normalized\r\n\r\n\t\t\t_q1.setFromAxisAngle( axis, angle );\r\n\r\n\t\t\tthis.quaternion.multiply( _q1 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateOnWorldAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// rotate object on axis in world space\r\n\t\t\t// axis is assumed to be normalized\r\n\t\t\t// method assumes no rotated parent\r\n\r\n\t\t\t_q1.setFromAxisAngle( axis, angle );\r\n\r\n\t\t\tthis.quaternion.premultiply( _q1 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _xAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _yAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _zAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateOnAxis: function ( axis, distance ) {\r\n\r\n\t\t\t// translate object by distance along axis in object space\r\n\t\t\t// axis is assumed to be normalized\r\n\r\n\t\t\t_v1$1.copy( axis ).applyQuaternion( this.quaternion );\r\n\r\n\t\t\tthis.position.add( _v1$1.multiplyScalar( distance ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslateX: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _xAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateY: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _yAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateZ: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _zAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\tlocalToWorld: function ( vector ) {\r\n\r\n\t\t\treturn vector.applyMatrix4( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tworldToLocal: function ( vector ) {\r\n\r\n\t\t\treturn vector.applyMatrix4( _m1$1.getInverse( this.matrixWorld ) );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( x, y, z ) {\r\n\r\n\t\t\t// This method does not support objects having non-uniformly-scaled parent(s)\r\n\r\n\t\t\tif ( x.isVector3 ) {\r\n\r\n\t\t\t\t_target.copy( x );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_target.set( x, y, z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tthis.updateWorldMatrix( true, false );\r\n\r\n\t\t\t_position.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\tif ( this.isCamera || this.isLight ) {\r\n\r\n\t\t\t\t_m1$1.lookAt( _position, _target, this.up );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_m1$1.lookAt( _target, _position, this.up );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.quaternion.setFromRotationMatrix( _m1$1 );\r\n\r\n\t\t\tif ( parent ) {\r\n\r\n\t\t\t\t_m1$1.extractRotation( parent.matrixWorld );\r\n\t\t\t\t_q1.setFromRotationMatrix( _m1$1 );\r\n\t\t\t\tthis.quaternion.premultiply( _q1.inverse() );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( object ) {\r\n\r\n\t\t\tif ( arguments.length > 1 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\r\n\r\n\t\t\t\t\tthis.add( arguments[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object === this ) {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Object3D.add: object can't be added as a child of itself.\", object );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( object && object.isObject3D ) ) {\r\n\r\n\t\t\t\tif ( object.parent !== null ) {\r\n\r\n\t\t\t\t\tobject.parent.remove( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tobject.parent = this;\r\n\t\t\t\tthis.children.push( object );\r\n\r\n\t\t\t\tobject.dispatchEvent( _addedEvent );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Object3D.add: object not an instance of THREE.Object3D.\", object );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tremove: function ( object ) {\r\n\r\n\t\t\tif ( arguments.length > 1 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\r\n\r\n\t\t\t\t\tthis.remove( arguments[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar index = this.children.indexOf( object );\r\n\r\n\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\tobject.parent = null;\r\n\t\t\t\tthis.children.splice( index, 1 );\r\n\r\n\t\t\t\tobject.dispatchEvent( _removedEvent );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tattach: function ( object ) {\r\n\r\n\t\t\t// adds object as a child of this, while maintaining the object's world transform\r\n\r\n\t\t\tthis.updateWorldMatrix( true, false );\r\n\r\n\t\t\t_m1$1.getInverse( this.matrixWorld );\r\n\r\n\t\t\tif ( object.parent !== null ) {\r\n\r\n\t\t\t\tobject.parent.updateWorldMatrix( true, false );\r\n\r\n\t\t\t\t_m1$1.multiply( object.parent.matrixWorld );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.applyMatrix( _m1$1 );\r\n\r\n\t\t\tobject.updateWorldMatrix( false, false );\r\n\r\n\t\t\tthis.add( object );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectById: function ( id ) {\r\n\r\n\t\t\treturn this.getObjectByProperty( 'id', id );\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectByName: function ( name ) {\r\n\r\n\t\t\treturn this.getObjectByProperty( 'name', name );\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectByProperty: function ( name, value ) {\r\n\r\n\t\t\tif ( this[ name ] === value ) { return this; }\r\n\r\n\t\t\tfor ( var i = 0, l = this.children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar child = this.children[ i ];\r\n\t\t\t\tvar object = child.getObjectByProperty( name, value );\r\n\r\n\t\t\t\tif ( object !== undefined ) {\r\n\r\n\t\t\t\t\treturn object;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldPosition: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\treturn target.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldQuaternion: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );\r\n\t\t\t\ttarget = new Quaternion();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position, target, _scale );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldScale: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldScale() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position, _quaternion$2, target );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldDirection: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tvar e = this.matrixWorld.elements;\r\n\r\n\t\t\treturn target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\traycast: function () {},\r\n\r\n\t\ttraverse: function ( callback ) {\r\n\r\n\t\t\tcallback( this );\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].traverse( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttraverseVisible: function ( callback ) {\r\n\r\n\t\t\tif ( this.visible === false ) { return; }\r\n\r\n\t\t\tcallback( this );\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].traverseVisible( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttraverseAncestors: function ( callback ) {\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tif ( parent !== null ) {\r\n\r\n\t\t\t\tcallback( parent );\r\n\r\n\t\t\t\tparent.traverseAncestors( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrix: function () {\r\n\r\n\t\t\tthis.matrix.compose( this.position, this.quaternion, this.scale );\r\n\r\n\t\t\tthis.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tif ( this.matrixWorldNeedsUpdate || force ) {\r\n\r\n\t\t\t\tif ( this.parent === null ) {\r\n\r\n\t\t\t\t\tthis.matrixWorld.copy( this.matrix );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.matrixWorldNeedsUpdate = false;\r\n\r\n\t\t\t\tforce = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update children\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( force );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tif ( updateParents === true && parent !== null ) {\r\n\r\n\t\t\t\tparent.updateWorldMatrix( true, false );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tif ( this.parent === null ) {\r\n\r\n\t\t\t\tthis.matrixWorld.copy( this.matrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update children\r\n\r\n\t\t\tif ( updateChildren === true ) {\r\n\r\n\t\t\t\tvar children = this.children;\r\n\r\n\t\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tchildren[ i ].updateWorldMatrix( false, true );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\t// meta is a string when called from JSON.stringify\r\n\t\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tvar output = {};\r\n\r\n\t\t\t// meta is a hash used to collect geometries, materials.\r\n\t\t\t// not providing it implies that this is the root object\r\n\t\t\t// being serialized.\r\n\t\t\tif ( isRootObject ) {\r\n\r\n\t\t\t\t// initialize meta obj\r\n\t\t\t\tmeta = {\r\n\t\t\t\t\tgeometries: {},\r\n\t\t\t\t\tmaterials: {},\r\n\t\t\t\t\ttextures: {},\r\n\t\t\t\t\timages: {},\r\n\t\t\t\t\tshapes: {}\r\n\t\t\t\t};\r\n\r\n\t\t\t\toutput.metadata = {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Object',\r\n\t\t\t\t\tgenerator: 'Object3D.toJSON'\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// standard Object3D serialization\r\n\r\n\t\t\tvar object = {};\r\n\r\n\t\t\tobject.uuid = this.uuid;\r\n\t\t\tobject.type = this.type;\r\n\r\n\t\t\tif ( this.name !== '' ) { object.name = this.name; }\r\n\t\t\tif ( this.castShadow === true ) { object.castShadow = true; }\r\n\t\t\tif ( this.receiveShadow === true ) { object.receiveShadow = true; }\r\n\t\t\tif ( this.visible === false ) { object.visible = false; }\r\n\t\t\tif ( this.frustumCulled === false ) { object.frustumCulled = false; }\r\n\t\t\tif ( this.renderOrder !== 0 ) { object.renderOrder = this.renderOrder; }\r\n\t\t\tif ( JSON.stringify( this.userData ) !== '{}' ) { object.userData = this.userData; }\r\n\r\n\t\t\tobject.layers = this.layers.mask;\r\n\t\t\tobject.matrix = this.matrix.toArray();\r\n\r\n\t\t\tif ( this.matrixAutoUpdate === false ) { object.matrixAutoUpdate = false; }\r\n\r\n\t\t\t// object specific properties\r\n\r\n\t\t\tif ( this.isInstancedMesh ) {\r\n\r\n\t\t\t\tobject.type = 'InstancedMesh';\r\n\t\t\t\tobject.count = this.count;\r\n\t\t\t\tobject.instanceMatrix = this.instanceMatrix.toJSON();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfunction serialize( library, element ) {\r\n\r\n\t\t\t\tif ( library[ element.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\tlibrary[ element.uuid ] = element.toJSON( meta );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn element.uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.isMesh || this.isLine || this.isPoints ) {\r\n\r\n\t\t\t\tobject.geometry = serialize( meta.geometries, this.geometry );\r\n\r\n\t\t\t\tvar parameters = this.geometry.parameters;\r\n\r\n\t\t\t\tif ( parameters !== undefined && parameters.shapes !== undefined ) {\r\n\r\n\t\t\t\t\tvar shapes = parameters.shapes;\r\n\r\n\t\t\t\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\t\t\t\tserialize( meta.shapes, shape );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tserialize( meta.shapes, shapes );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.material !== undefined ) {\r\n\r\n\t\t\t\tif ( Array.isArray( this.material ) ) {\r\n\r\n\t\t\t\t\tvar uuids = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = this.material.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\tuuids.push( serialize( meta.materials, this.material[ i ] ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tobject.material = uuids;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tobject.material = serialize( meta.materials, this.material );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.children.length > 0 ) {\r\n\r\n\t\t\t\tobject.children = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < this.children.length; i ++ ) {\r\n\r\n\t\t\t\t\tobject.children.push( this.children[ i ].toJSON( meta ).object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isRootObject ) {\r\n\r\n\t\t\t\tvar geometries = extractFromCache( meta.geometries );\r\n\t\t\t\tvar materials = extractFromCache( meta.materials );\r\n\t\t\t\tvar textures = extractFromCache( meta.textures );\r\n\t\t\t\tvar images = extractFromCache( meta.images );\r\n\t\t\t\tvar shapes = extractFromCache( meta.shapes );\r\n\r\n\t\t\t\tif ( geometries.length > 0 ) { output.geometries = geometries; }\r\n\t\t\t\tif ( materials.length > 0 ) { output.materials = materials; }\r\n\t\t\t\tif ( textures.length > 0 ) { output.textures = textures; }\r\n\t\t\t\tif ( images.length > 0 ) { output.images = images; }\r\n\t\t\t\tif ( shapes.length > 0 ) { output.shapes = shapes; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\toutput.object = object;\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t\t// extract data from the cache hash\r\n\t\t\t// remove metadata on each item\r\n\t\t\t// and return as array\r\n\t\t\tfunction extractFromCache( cache ) {\r\n\r\n\t\t\t\tvar values = [];\r\n\t\t\t\tfor ( var key in cache ) {\r\n\r\n\t\t\t\t\tvar data = cache[ key ];\r\n\t\t\t\t\tdelete data.metadata;\r\n\t\t\t\t\tvalues.push( data );\r\n\r\n\t\t\t\t}\r\n\t\t\t\treturn values;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function ( recursive ) {\r\n\r\n\t\t\treturn new this.constructor().copy( this, recursive );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tif ( recursive === undefined ) { recursive = true; }\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.up.copy( source.up );\r\n\r\n\t\t\tthis.position.copy( source.position );\r\n\t\t\tthis.quaternion.copy( source.quaternion );\r\n\t\t\tthis.scale.copy( source.scale );\r\n\r\n\t\t\tthis.matrix.copy( source.matrix );\r\n\t\t\tthis.matrixWorld.copy( source.matrixWorld );\r\n\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\t\t\tthis.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;\r\n\r\n\t\t\tthis.layers.mask = source.layers.mask;\r\n\t\t\tthis.visible = source.visible;\r\n\r\n\t\t\tthis.castShadow = source.castShadow;\r\n\t\t\tthis.receiveShadow = source.receiveShadow;\r\n\r\n\t\t\tthis.frustumCulled = source.frustumCulled;\r\n\t\t\tthis.renderOrder = source.renderOrder;\r\n\r\n\t\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\r\n\r\n\t\t\tif ( recursive === true ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < source.children.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar child = source.children[ i ];\r\n\t\t\t\t\tthis.add( child.clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Scene() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Scene';\r\n\r\n\t\tthis.background = null;\r\n\t\tthis.fog = null;\r\n\t\tthis.overrideMaterial = null;\r\n\r\n\t\tthis.autoUpdate = true; // checked by the renderer\r\n\r\n\t\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tScene.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Scene,\r\n\r\n\t\tisScene: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tif ( source.background !== null ) { this.background = source.background.clone(); }\r\n\t\t\tif ( source.fog !== null ) { this.fog = source.fog.clone(); }\r\n\t\t\tif ( source.overrideMaterial !== null ) { this.overrideMaterial = source.overrideMaterial.clone(); }\r\n\r\n\t\t\tthis.autoUpdate = source.autoUpdate;\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tif ( this.background !== null ) { data.object.background = this.background.toJSON( meta ); }\r\n\t\t\tif ( this.fog !== null ) { data.object.fog = this.fog.toJSON(); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _points = [\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3()\r\n\t];\r\n\r\n\tvar _vector$2 = new Vector3();\r\n\r\n\tvar _box = new Box3();\r\n\r\n\t// triangle centered vertices\r\n\r\n\tvar _v0 = new Vector3();\r\n\tvar _v1$2 = new Vector3();\r\n\tvar _v2 = new Vector3();\r\n\r\n\t// triangle edge vectors\r\n\r\n\tvar _f0 = new Vector3();\r\n\tvar _f1 = new Vector3();\r\n\tvar _f2 = new Vector3();\r\n\r\n\tvar _center = new Vector3();\r\n\tvar _extents = new Vector3();\r\n\tvar _triangleNormal = new Vector3();\r\n\tvar _testAxis = new Vector3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Box3( min, max ) {\r\n\r\n\t\tthis.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );\r\n\t\tthis.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );\r\n\r\n\t}\r\n\r\n\r\n\tObject.assign( Box3.prototype, {\r\n\r\n\t\tisBox3: true,\r\n\r\n\t\tset: function ( min, max ) {\r\n\r\n\t\t\tthis.min.copy( min );\r\n\t\t\tthis.max.copy( max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromArray: function ( array ) {\r\n\r\n\t\t\tvar minX = + Infinity;\r\n\t\t\tvar minY = + Infinity;\r\n\t\t\tvar minZ = + Infinity;\r\n\r\n\t\t\tvar maxX = - Infinity;\r\n\t\t\tvar maxY = - Infinity;\r\n\t\t\tvar maxZ = - Infinity;\r\n\r\n\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\r\n\r\n\t\t\t\tvar x = array[ i ];\r\n\t\t\t\tvar y = array[ i + 1 ];\r\n\t\t\t\tvar z = array[ i + 2 ];\r\n\r\n\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\tif ( z < minZ ) { minZ = z; }\r\n\r\n\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\t\t\t\tif ( z > maxZ ) { maxZ = z; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.min.set( minX, minY, minZ );\r\n\t\t\tthis.max.set( maxX, maxY, maxZ );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tvar minX = + Infinity;\r\n\t\t\tvar minY = + Infinity;\r\n\t\t\tvar minZ = + Infinity;\r\n\r\n\t\t\tvar maxX = - Infinity;\r\n\t\t\tvar maxY = - Infinity;\r\n\t\t\tvar maxZ = - Infinity;\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar x = attribute.getX( i );\r\n\t\t\t\tvar y = attribute.getY( i );\r\n\t\t\t\tvar z = attribute.getZ( i );\r\n\r\n\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\tif ( z < minZ ) { minZ = z; }\r\n\r\n\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\t\t\t\tif ( z > maxZ ) { maxZ = z; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.min.set( minX, minY, minZ );\r\n\t\t\tthis.max.set( maxX, maxY, maxZ );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByPoint( points[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCenterAndSize: function ( center, size ) {\r\n\r\n\t\t\tvar halfSize = _vector$2.copy( size ).multiplyScalar( 0.5 );\r\n\r\n\t\t\tthis.min.copy( center ).sub( halfSize );\r\n\t\t\tthis.max.copy( center ).add( halfSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromObject: function ( object ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\treturn this.expandByObject( object );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( box ) {\r\n\r\n\t\t\tthis.min.copy( box.min );\r\n\t\t\tthis.max.copy( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeEmpty: function () {\r\n\r\n\t\t\tthis.min.x = this.min.y = this.min.z = + Infinity;\r\n\t\t\tthis.max.x = this.max.y = this.max.z = - Infinity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tisEmpty: function () {\r\n\r\n\t\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\r\n\r\n\t\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tgetSize: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getSize() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );\r\n\r\n\t\t},\r\n\r\n\t\texpandByPoint: function ( point ) {\r\n\r\n\t\t\tthis.min.min( point );\r\n\t\t\tthis.max.max( point );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByVector: function ( vector ) {\r\n\r\n\t\t\tthis.min.sub( vector );\r\n\t\t\tthis.max.add( vector );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.min.addScalar( - scalar );\r\n\t\t\tthis.max.addScalar( scalar );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByObject: function ( object ) {\r\n\r\n\t\t\t// Computes the world-axis-aligned bounding box of an object (including its children),\r\n\t\t\t// accounting for both the object's, and children's, world transforms\r\n\r\n\t\t\tobject.updateWorldMatrix( false, false );\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( geometry !== undefined ) {\r\n\r\n\t\t\t\tif ( geometry.boundingBox === null ) {\r\n\r\n\t\t\t\t\tgeometry.computeBoundingBox();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_box.copy( geometry.boundingBox );\r\n\t\t\t\t_box.applyMatrix4( object.matrixWorld );\r\n\r\n\t\t\t\tthis.expandByPoint( _box.min );\r\n\t\t\t\tthis.expandByPoint( _box.max );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByObject( children[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn point.x < this.min.x || point.x > this.max.x ||\r\n\t\t\t\tpoint.y < this.min.y || point.y > this.max.y ||\r\n\t\t\t\tpoint.z < this.min.z || point.z > this.max.z ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsBox: function ( box ) {\r\n\r\n\t\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\r\n\t\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y &&\r\n\t\t\t\tthis.min.z <= box.min.z && box.max.z <= this.max.z;\r\n\r\n\t\t},\r\n\r\n\t\tgetParameter: function ( point, target ) {\r\n\r\n\t\t\t// This can potentially have a divide by zero if the box\r\n\t\t\t// has a size dimension of 0.\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getParameter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set(\r\n\t\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\r\n\t\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y ),\r\n\t\t\t\t( point.z - this.min.z ) / ( this.max.z - this.min.z )\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\t// using 6 splitting planes to rule out intersections.\r\n\t\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\r\n\t\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ||\r\n\t\t\t\tbox.max.z < this.min.z || box.min.z > this.max.z ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\t// Find the point on the AABB closest to the sphere center.\r\n\t\t\tthis.clampPoint( sphere.center, _vector$2 );\r\n\r\n\t\t\t// If that point is inside the sphere, the AABB and sphere intersect.\r\n\t\t\treturn _vector$2.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\t// We compute the minimum and maximum dot product values. If those values\r\n\t\t\t// are on the same side (back or front) of the plane, then there is no intersection.\r\n\r\n\t\t\tvar min, max;\r\n\r\n\t\t\tif ( plane.normal.x > 0 ) {\r\n\r\n\t\t\t\tmin = plane.normal.x * this.min.x;\r\n\t\t\t\tmax = plane.normal.x * this.max.x;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin = plane.normal.x * this.max.x;\r\n\t\t\t\tmax = plane.normal.x * this.min.x;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( plane.normal.y > 0 ) {\r\n\r\n\t\t\t\tmin += plane.normal.y * this.min.y;\r\n\t\t\t\tmax += plane.normal.y * this.max.y;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin += plane.normal.y * this.max.y;\r\n\t\t\t\tmax += plane.normal.y * this.min.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( plane.normal.z > 0 ) {\r\n\r\n\t\t\t\tmin += plane.normal.z * this.min.z;\r\n\t\t\t\tmax += plane.normal.z * this.max.z;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin += plane.normal.z * this.max.z;\r\n\t\t\t\tmax += plane.normal.z * this.min.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn ( min <= - plane.constant && max >= - plane.constant );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsTriangle: function ( triangle ) {\r\n\r\n\t\t\tif ( this.isEmpty() ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// compute box center and extents\r\n\t\t\tthis.getCenter( _center );\r\n\t\t\t_extents.subVectors( this.max, _center );\r\n\r\n\t\t\t// translate triangle to aabb origin\r\n\t\t\t_v0.subVectors( triangle.a, _center );\r\n\t\t\t_v1$2.subVectors( triangle.b, _center );\r\n\t\t\t_v2.subVectors( triangle.c, _center );\r\n\r\n\t\t\t// compute edge vectors for triangle\r\n\t\t\t_f0.subVectors( _v1$2, _v0 );\r\n\t\t\t_f1.subVectors( _v2, _v1$2 );\r\n\t\t\t_f2.subVectors( _v0, _v2 );\r\n\r\n\t\t\t// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb\r\n\t\t\t// make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation\r\n\t\t\t// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)\r\n\t\t\tvar axes = [\r\n\t\t\t\t0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,\r\n\t\t\t\t_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,\r\n\t\t\t\t- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0\r\n\t\t\t];\r\n\t\t\tif ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// test 3 face normals from the aabb\r\n\t\t\taxes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];\r\n\t\t\tif ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// finally testing the face normal of the triangle\r\n\t\t\t// use already existing triangle edge vectors here\r\n\t\t\t_triangleNormal.crossVectors( _f0, _f1 );\r\n\t\t\taxes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];\r\n\r\n\t\t\treturn satForAxes( axes, _v0, _v1$2, _v2, _extents );\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\tvar clampedPoint = _vector$2.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t\treturn clampedPoint.sub( point ).length();\r\n\r\n\t\t},\r\n\r\n\t\tgetBoundingSphere: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Box3: .getBoundingSphere() target is now required' );\r\n\t\t\t\t//target = new Sphere(); // removed to avoid cyclic dependency\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.getCenter( target.center );\r\n\r\n\t\t\ttarget.radius = this.getSize( _vector$2 ).length() * 0.5;\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tintersect: function ( box ) {\r\n\r\n\t\t\tthis.min.max( box.min );\r\n\t\t\tthis.max.min( box.max );\r\n\r\n\t\t\t// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.\r\n\t\t\tif ( this.isEmpty() ) { this.makeEmpty(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tunion: function ( box ) {\r\n\r\n\t\t\tthis.min.min( box.min );\r\n\t\t\tthis.max.max( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\t// transform of empty box is an empty box.\r\n\t\t\tif ( this.isEmpty() ) { return this; }\r\n\r\n\t\t\t// NOTE: I am using a binary pattern to specify all 2^3 combinations below\r\n\t\t\t_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000\r\n\t\t\t_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001\r\n\t\t\t_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010\r\n\t\t\t_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011\r\n\t\t\t_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100\r\n\t\t\t_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101\r\n\t\t\t_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110\r\n\t\t\t_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111\r\n\r\n\t\t\tthis.setFromPoints( _points );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.min.add( offset );\r\n\t\t\tthis.max.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( box ) {\r\n\r\n\t\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction satForAxes( axes, v0, v1, v2, extents ) {\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tfor ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {\r\n\r\n\t\t\t_testAxis.fromArray( axes, i );\r\n\t\t\t// project the aabb onto the seperating axis\r\n\t\t\tvar r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );\r\n\t\t\t// project all 3 vertices of the triangle onto the seperating axis\r\n\t\t\tvar p0 = v0.dot( _testAxis );\r\n\t\t\tvar p1 = v1.dot( _testAxis );\r\n\t\t\tvar p2 = v2.dot( _testAxis );\r\n\t\t\t// actual test, basically see if either of the most extreme of the triangle points intersects r\r\n\t\t\tif ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {\r\n\r\n\t\t\t\t// points of the projected triangle are outside the projected half-length of the aabb\r\n\t\t\t\t// the axis is seperating and we can exit\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\n\n\tvar _box$1 = new Box3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Sphere( center, radius ) {\r\n\r\n\t\tthis.center = ( center !== undefined ) ? center : new Vector3();\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Sphere.prototype, {\r\n\r\n\t\tset: function ( center, radius ) {\r\n\r\n\t\t\tthis.center.copy( center );\r\n\t\t\tthis.radius = radius;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points, optionalCenter ) {\r\n\r\n\t\t\tvar center = this.center;\r\n\r\n\t\t\tif ( optionalCenter !== undefined ) {\r\n\r\n\t\t\t\tcenter.copy( optionalCenter );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_box$1.setFromPoints( points ).getCenter( center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar maxRadiusSq = 0;\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.radius = Math.sqrt( maxRadiusSq );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( sphere ) {\r\n\r\n\t\t\tthis.center.copy( sphere.center );\r\n\t\t\tthis.radius = sphere.radius;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tempty: function () {\r\n\r\n\t\t\treturn ( this.radius <= 0 );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn ( point.distanceTo( this.center ) - this.radius );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\tvar radiusSum = this.radius + sphere.radius;\r\n\r\n\t\t\treturn sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsSphere( this );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\treturn Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tvar deltaLengthSq = this.center.distanceToSquared( point );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Sphere: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.copy( point );\r\n\r\n\t\t\tif ( deltaLengthSq > ( this.radius * this.radius ) ) {\r\n\r\n\t\t\t\ttarget.sub( this.center ).normalize();\r\n\t\t\t\ttarget.multiplyScalar( this.radius ).add( this.center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetBoundingBox: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );\r\n\t\t\t\ttarget = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.set( this.center, this.center );\r\n\t\t\ttarget.expandByScalar( this.radius );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\tthis.center.applyMatrix4( matrix );\r\n\t\t\tthis.radius = this.radius * matrix.getMaxScaleOnAxis();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.center.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( sphere ) {\r\n\r\n\t\t\treturn sphere.center.equals( this.center ) && ( sphere.radius === this.radius );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _vector$3 = new Vector3();\r\n\tvar _segCenter = new Vector3();\r\n\tvar _segDir = new Vector3();\r\n\tvar _diff = new Vector3();\r\n\r\n\tvar _edge1 = new Vector3();\r\n\tvar _edge2 = new Vector3();\r\n\tvar _normal = new Vector3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tfunction Ray( origin, direction ) {\r\n\r\n\t\tthis.origin = ( origin !== undefined ) ? origin : new Vector3();\r\n\t\tthis.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );\r\n\r\n\t}\r\n\r\n\tObject.assign( Ray.prototype, {\r\n\r\n\t\tset: function ( origin, direction ) {\r\n\r\n\t\t\tthis.origin.copy( origin );\r\n\t\t\tthis.direction.copy( direction );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( ray ) {\r\n\r\n\t\t\tthis.origin.copy( ray.origin );\r\n\t\t\tthis.direction.copy( ray.direction );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tat: function ( t, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Ray: .at() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.direction ).multiplyScalar( t ).add( this.origin );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( v ) {\r\n\r\n\t\t\tthis.direction.copy( v ).sub( this.origin ).normalize();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trecast: function ( t ) {\r\n\r\n\t\t\tthis.origin.copy( this.at( t, _vector$3 ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.subVectors( point, this.origin );\r\n\r\n\t\t\tvar directionDistance = target.dot( this.direction );\r\n\r\n\t\t\tif ( directionDistance < 0 ) {\r\n\r\n\t\t\t\treturn target.copy( this.origin );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceSqToPoint( point ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSqToPoint: function ( point ) {\r\n\r\n\t\t\tvar directionDistance = _vector$3.subVectors( point, this.origin ).dot( this.direction );\r\n\r\n\t\t\t// point behind the ray\r\n\r\n\t\t\tif ( directionDistance < 0 ) {\r\n\r\n\t\t\t\treturn this.origin.distanceToSquared( point );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vector$3.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\r\n\r\n\t\t\treturn _vector$3.distanceToSquared( point );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {\r\n\r\n\t\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h\r\n\t\t\t// It returns the min distance between the ray and the segment\r\n\t\t\t// defined by v0 and v1\r\n\t\t\t// It can also set two optional targets :\r\n\t\t\t// - The closest point on the ray\r\n\t\t\t// - The closest point on the segment\r\n\r\n\t\t\t_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );\r\n\t\t\t_segDir.copy( v1 ).sub( v0 ).normalize();\r\n\t\t\t_diff.copy( this.origin ).sub( _segCenter );\r\n\r\n\t\t\tvar segExtent = v0.distanceTo( v1 ) * 0.5;\r\n\t\t\tvar a01 = - this.direction.dot( _segDir );\r\n\t\t\tvar b0 = _diff.dot( this.direction );\r\n\t\t\tvar b1 = - _diff.dot( _segDir );\r\n\t\t\tvar c = _diff.lengthSq();\r\n\t\t\tvar det = Math.abs( 1 - a01 * a01 );\r\n\t\t\tvar s0, s1, sqrDist, extDet;\r\n\r\n\t\t\tif ( det > 0 ) {\r\n\r\n\t\t\t\t// The ray and segment are not parallel.\r\n\r\n\t\t\t\ts0 = a01 * b1 - b0;\r\n\t\t\t\ts1 = a01 * b0 - b1;\r\n\t\t\t\textDet = segExtent * det;\r\n\r\n\t\t\t\tif ( s0 >= 0 ) {\r\n\r\n\t\t\t\t\tif ( s1 >= - extDet ) {\r\n\r\n\t\t\t\t\t\tif ( s1 <= extDet ) {\r\n\r\n\t\t\t\t\t\t\t// region 0\r\n\t\t\t\t\t\t\t// Minimum at interior points of ray and segment.\r\n\r\n\t\t\t\t\t\t\tvar invDet = 1 / det;\r\n\t\t\t\t\t\t\ts0 *= invDet;\r\n\t\t\t\t\t\t\ts1 *= invDet;\r\n\t\t\t\t\t\t\tsqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t// region 1\r\n\r\n\t\t\t\t\t\t\ts1 = segExtent;\r\n\t\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// region 5\r\n\r\n\t\t\t\t\t\ts1 = - segExtent;\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tif ( s1 <= - extDet ) {\r\n\r\n\t\t\t\t\t\t// region 4\r\n\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );\r\n\t\t\t\t\t\ts1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t} else if ( s1 <= extDet ) {\r\n\r\n\t\t\t\t\t\t// region 3\r\n\r\n\t\t\t\t\t\ts0 = 0;\r\n\t\t\t\t\t\ts1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// region 2\r\n\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * segExtent + b0 ) );\r\n\t\t\t\t\t\ts1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Ray and segment are parallel.\r\n\r\n\t\t\t\ts1 = ( a01 > 0 ) ? - segExtent : segExtent;\r\n\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( optionalPointOnRay ) {\r\n\r\n\t\t\t\toptionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( optionalPointOnSegment ) {\r\n\r\n\t\t\t\toptionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn sqrDist;\r\n\r\n\t\t},\r\n\r\n\t\tintersectSphere: function ( sphere, target ) {\r\n\r\n\t\t\t_vector$3.subVectors( sphere.center, this.origin );\r\n\t\t\tvar tca = _vector$3.dot( this.direction );\r\n\t\t\tvar d2 = _vector$3.dot( _vector$3 ) - tca * tca;\r\n\t\t\tvar radius2 = sphere.radius * sphere.radius;\r\n\r\n\t\t\tif ( d2 > radius2 ) { return null; }\r\n\r\n\t\t\tvar thc = Math.sqrt( radius2 - d2 );\r\n\r\n\t\t\t// t0 = first intersect point - entrance on front of sphere\r\n\t\t\tvar t0 = tca - thc;\r\n\r\n\t\t\t// t1 = second intersect point - exit point on back of sphere\r\n\t\t\tvar t1 = tca + thc;\r\n\r\n\t\t\t// test to see if both t0 and t1 are behind the ray - if so, return null\r\n\t\t\tif ( t0 < 0 && t1 < 0 ) { return null; }\r\n\r\n\t\t\t// test to see if t0 is behind the ray:\r\n\t\t\t// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,\r\n\t\t\t// in order to always return an intersect point that is in front of the ray.\r\n\t\t\tif ( t0 < 0 ) { return this.at( t1, target ); }\r\n\r\n\t\t\t// else t0 is in front of the ray, so return the first collision point scaled by t0\r\n\t\t\treturn this.at( t0, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\treturn this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPlane: function ( plane ) {\r\n\r\n\t\t\tvar denominator = plane.normal.dot( this.direction );\r\n\r\n\t\t\tif ( denominator === 0 ) {\r\n\r\n\t\t\t\t// line is coplanar, return origin\r\n\t\t\t\tif ( plane.distanceToPoint( this.origin ) === 0 ) {\r\n\r\n\t\t\t\t\treturn 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Null is preferable to undefined since undefined means.... it is undefined\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;\r\n\r\n\t\t\t// Return if the ray never intersects the plane\r\n\r\n\t\t\treturn t >= 0 ? t : null;\r\n\r\n\t\t},\r\n\r\n\t\tintersectPlane: function ( plane, target ) {\r\n\r\n\t\t\tvar t = this.distanceToPlane( plane );\r\n\r\n\t\t\tif ( t === null ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.at( t, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\t// check if the ray lies on the plane first\r\n\r\n\t\t\tvar distToPoint = plane.distanceToPoint( this.origin );\r\n\r\n\t\t\tif ( distToPoint === 0 ) {\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar denominator = plane.normal.dot( this.direction );\r\n\r\n\t\t\tif ( denominator * distToPoint < 0 ) {\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// ray origin is behind the plane (and is pointing behind it)\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t},\r\n\r\n\t\tintersectBox: function ( box, target ) {\r\n\r\n\t\t\tvar tmin, tmax, tymin, tymax, tzmin, tzmax;\r\n\r\n\t\t\tvar invdirx = 1 / this.direction.x,\r\n\t\t\t\tinvdiry = 1 / this.direction.y,\r\n\t\t\t\tinvdirz = 1 / this.direction.z;\r\n\r\n\t\t\tvar origin = this.origin;\r\n\r\n\t\t\tif ( invdirx >= 0 ) {\r\n\r\n\t\t\t\ttmin = ( box.min.x - origin.x ) * invdirx;\r\n\t\t\t\ttmax = ( box.max.x - origin.x ) * invdirx;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttmin = ( box.max.x - origin.x ) * invdirx;\r\n\t\t\t\ttmax = ( box.min.x - origin.x ) * invdirx;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( invdiry >= 0 ) {\r\n\r\n\t\t\t\ttymin = ( box.min.y - origin.y ) * invdiry;\r\n\t\t\t\ttymax = ( box.max.y - origin.y ) * invdiry;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttymin = ( box.max.y - origin.y ) * invdiry;\r\n\t\t\t\ttymax = ( box.min.y - origin.y ) * invdiry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( tmin > tymax ) || ( tymin > tmax ) ) { return null; }\r\n\r\n\t\t\t// These lines also handle the case where tmin or tmax is NaN\r\n\t\t\t// (result of 0 * Infinity). x !== x returns true if x is NaN\r\n\r\n\t\t\tif ( tymin > tmin || tmin !== tmin ) { tmin = tymin; }\r\n\r\n\t\t\tif ( tymax < tmax || tmax !== tmax ) { tmax = tymax; }\r\n\r\n\t\t\tif ( invdirz >= 0 ) {\r\n\r\n\t\t\t\ttzmin = ( box.min.z - origin.z ) * invdirz;\r\n\t\t\t\ttzmax = ( box.max.z - origin.z ) * invdirz;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttzmin = ( box.max.z - origin.z ) * invdirz;\r\n\t\t\t\ttzmax = ( box.min.z - origin.z ) * invdirz;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( tmin > tzmax ) || ( tzmin > tmax ) ) { return null; }\r\n\r\n\t\t\tif ( tzmin > tmin || tmin !== tmin ) { tmin = tzmin; }\r\n\r\n\t\t\tif ( tzmax < tmax || tmax !== tmax ) { tmax = tzmax; }\r\n\r\n\t\t\t//return point closest to the ray (positive side)\r\n\r\n\t\t\tif ( tmax < 0 ) { return null; }\r\n\r\n\t\t\treturn this.at( tmin >= 0 ? tmin : tmax, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn this.intersectBox( box, _vector$3 ) !== null;\r\n\r\n\t\t},\r\n\r\n\t\tintersectTriangle: function ( a, b, c, backfaceCulling, target ) {\r\n\r\n\t\t\t// Compute the offset origin, edges, and normal.\r\n\r\n\t\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h\r\n\r\n\t\t\t_edge1.subVectors( b, a );\r\n\t\t\t_edge2.subVectors( c, a );\r\n\t\t\t_normal.crossVectors( _edge1, _edge2 );\r\n\r\n\t\t\t// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,\r\n\t\t\t// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by\r\n\t\t\t// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))\r\n\t\t\t// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))\r\n\t\t\t// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)\r\n\t\t\tvar DdN = this.direction.dot( _normal );\r\n\t\t\tvar sign;\r\n\r\n\t\t\tif ( DdN > 0 ) {\r\n\r\n\t\t\t\tif ( backfaceCulling ) { return null; }\r\n\t\t\t\tsign = 1;\r\n\r\n\t\t\t} else if ( DdN < 0 ) {\r\n\r\n\t\t\t\tsign = - 1;\r\n\t\t\t\tDdN = - DdN;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_diff.subVectors( this.origin, a );\r\n\t\t\tvar DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );\r\n\r\n\t\t\t// b1 < 0, no intersection\r\n\t\t\tif ( DdQxE2 < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );\r\n\r\n\t\t\t// b2 < 0, no intersection\r\n\t\t\tif ( DdE1xQ < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// b1+b2 > 1, no intersection\r\n\t\t\tif ( DdQxE2 + DdE1xQ > DdN ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Line intersects triangle, check if ray does.\r\n\t\t\tvar QdN = - sign * _diff.dot( _normal );\r\n\r\n\t\t\t// t < 0, no intersection\r\n\t\t\tif ( QdN < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Ray intersects triangle.\r\n\t\t\treturn this.at( QdN / DdN, target );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix4 ) {\r\n\r\n\t\t\tthis.origin.applyMatrix4( matrix4 );\r\n\t\t\tthis.direction.transformDirection( matrix4 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( ray ) {\r\n\r\n\t\t\treturn ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _vector1 = new Vector3();\r\n\tvar _vector2 = new Vector3();\r\n\tvar _normalMatrix = new Matrix3();\r\n\r\n\tfunction Plane( normal, constant ) {\r\n\r\n\t\t// normal is assumed to be normalized\r\n\r\n\t\tthis.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );\r\n\t\tthis.constant = ( constant !== undefined ) ? constant : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Plane.prototype, {\r\n\r\n\t\tisPlane: true,\r\n\r\n\t\tset: function ( normal, constant ) {\r\n\r\n\t\t\tthis.normal.copy( normal );\r\n\t\t\tthis.constant = constant;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponents: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis.normal.set( x, y, z );\r\n\t\t\tthis.constant = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromNormalAndCoplanarPoint: function ( normal, point ) {\r\n\r\n\t\t\tthis.normal.copy( normal );\r\n\t\t\tthis.constant = - point.dot( this.normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCoplanarPoints: function ( a, b, c ) {\r\n\r\n\t\t\tvar normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();\r\n\r\n\t\t\t// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?\r\n\r\n\t\t\tthis.setFromNormalAndCoplanarPoint( normal, a );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( plane ) {\r\n\r\n\t\t\tthis.normal.copy( plane.normal );\r\n\t\t\tthis.constant = plane.constant;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\t// Note: will lead to a divide by zero if the plane is invalid.\r\n\r\n\t\t\tvar inverseNormalLength = 1.0 / this.normal.length();\r\n\t\t\tthis.normal.multiplyScalar( inverseNormalLength );\r\n\t\t\tthis.constant *= inverseNormalLength;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.constant *= - 1;\r\n\t\t\tthis.normal.negate();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn this.normal.dot( point ) + this.constant;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSphere: function ( sphere ) {\r\n\r\n\t\t\treturn this.distanceToPoint( sphere.center ) - sphere.radius;\r\n\r\n\t\t},\r\n\r\n\t\tprojectPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .projectPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );\r\n\r\n\t\t},\r\n\r\n\t\tintersectLine: function ( line, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .intersectLine() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar direction = line.delta( _vector1 );\r\n\r\n\t\t\tvar denominator = this.normal.dot( direction );\r\n\r\n\t\t\tif ( denominator === 0 ) {\r\n\r\n\t\t\t\t// line is coplanar, return origin\r\n\t\t\t\tif ( this.distanceToPoint( line.start ) === 0 ) {\r\n\r\n\t\t\t\t\treturn target.copy( line.start );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Unsure if this is the correct method to handle this case.\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;\r\n\r\n\t\t\tif ( t < 0 || t > 1 ) {\r\n\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( direction ).multiplyScalar( t ).add( line.start );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsLine: function ( line ) {\r\n\r\n\t\t\t// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.\r\n\r\n\t\t\tvar startSign = this.distanceToPoint( line.start );\r\n\t\t\tvar endSign = this.distanceToPoint( line.end );\r\n\r\n\t\t\treturn ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsPlane( this );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\treturn sphere.intersectsPlane( this );\r\n\r\n\t\t},\r\n\r\n\t\tcoplanarPoint: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .coplanarPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.normal ).multiplyScalar( - this.constant );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix, optionalNormalMatrix ) {\r\n\r\n\t\t\tvar normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );\r\n\r\n\t\t\tvar referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );\r\n\r\n\t\t\tvar normal = this.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\tthis.constant = - referencePoint.dot( normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.constant -= offset.dot( this.normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( plane ) {\r\n\r\n\t\t\treturn plane.normal.equals( this.normal ) && ( plane.constant === this.constant );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _v0$1 = new Vector3();\r\n\tvar _v1$3 = new Vector3();\r\n\tvar _v2$1 = new Vector3();\r\n\tvar _v3 = new Vector3();\r\n\r\n\tvar _vab = new Vector3();\r\n\tvar _vac = new Vector3();\r\n\tvar _vbc = new Vector3();\r\n\tvar _vap = new Vector3();\r\n\tvar _vbp = new Vector3();\r\n\tvar _vcp = new Vector3();\r\n\r\n\tfunction Triangle( a, b, c ) {\r\n\r\n\t\tthis.a = ( a !== undefined ) ? a : new Vector3();\r\n\t\tthis.b = ( b !== undefined ) ? b : new Vector3();\r\n\t\tthis.c = ( c !== undefined ) ? c : new Vector3();\r\n\r\n\t}\r\n\r\n\tObject.assign( Triangle, {\r\n\r\n\t\tgetNormal: function ( a, b, c, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getNormal() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.subVectors( c, b );\r\n\t\t\t_v0$1.subVectors( a, b );\r\n\t\t\ttarget.cross( _v0$1 );\r\n\r\n\t\t\tvar targetLengthSq = target.lengthSq();\r\n\t\t\tif ( targetLengthSq > 0 ) {\r\n\r\n\t\t\t\treturn target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( 0, 0, 0 );\r\n\r\n\t\t},\r\n\r\n\t\t// static/instance method to calculate barycentric coordinates\r\n\t\t// based on: http://www.blackpawn.com/texts/pointinpoly/default.html\r\n\t\tgetBarycoord: function ( point, a, b, c, target ) {\r\n\r\n\t\t\t_v0$1.subVectors( c, a );\r\n\t\t\t_v1$3.subVectors( b, a );\r\n\t\t\t_v2$1.subVectors( point, a );\r\n\r\n\t\t\tvar dot00 = _v0$1.dot( _v0$1 );\r\n\t\t\tvar dot01 = _v0$1.dot( _v1$3 );\r\n\t\t\tvar dot02 = _v0$1.dot( _v2$1 );\r\n\t\t\tvar dot11 = _v1$3.dot( _v1$3 );\r\n\t\t\tvar dot12 = _v1$3.dot( _v2$1 );\r\n\r\n\t\t\tvar denom = ( dot00 * dot11 - dot01 * dot01 );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getBarycoord() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// collinear or singular triangle\r\n\t\t\tif ( denom === 0 ) {\r\n\r\n\t\t\t\t// arbitrary location outside of triangle?\r\n\t\t\t\t// not sure if this is the best idea, maybe should be returning undefined\r\n\t\t\t\treturn target.set( - 2, - 1, - 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar invDenom = 1 / denom;\r\n\t\t\tvar u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;\r\n\t\t\tvar v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;\r\n\r\n\t\t\t// barycentric coordinates must always sum to 1\r\n\t\t\treturn target.set( 1 - u - v, v, u );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point, a, b, c ) {\r\n\r\n\t\t\tTriangle.getBarycoord( point, a, b, c, _v3 );\r\n\r\n\t\t\treturn ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );\r\n\r\n\t\t},\r\n\r\n\t\tgetUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {\r\n\r\n\t\t\tthis.getBarycoord( point, p1, p2, p3, _v3 );\r\n\r\n\t\t\ttarget.set( 0, 0 );\r\n\t\t\ttarget.addScaledVector( uv1, _v3.x );\r\n\t\t\ttarget.addScaledVector( uv2, _v3.y );\r\n\t\t\ttarget.addScaledVector( uv3, _v3.z );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tisFrontFacing: function ( a, b, c, direction ) {\r\n\r\n\t\t\t_v0$1.subVectors( c, b );\r\n\t\t\t_v1$3.subVectors( a, b );\r\n\r\n\t\t\t// strictly front facing\r\n\t\t\treturn ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle.prototype, {\r\n\r\n\t\tset: function ( a, b, c ) {\r\n\r\n\t\t\tthis.a.copy( a );\r\n\t\t\tthis.b.copy( b );\r\n\t\t\tthis.c.copy( c );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPointsAndIndices: function ( points, i0, i1, i2 ) {\r\n\r\n\t\t\tthis.a.copy( points[ i0 ] );\r\n\t\t\tthis.b.copy( points[ i1 ] );\r\n\t\t\tthis.c.copy( points[ i2 ] );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( triangle ) {\r\n\r\n\t\t\tthis.a.copy( triangle.a );\r\n\t\t\tthis.b.copy( triangle.b );\r\n\t\t\tthis.c.copy( triangle.c );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetArea: function () {\r\n\r\n\t\t\t_v0$1.subVectors( this.c, this.b );\r\n\t\t\t_v1$3.subVectors( this.a, this.b );\r\n\r\n\t\t\treturn _v0$1.cross( _v1$3 ).length() * 0.5;\r\n\r\n\t\t},\r\n\r\n\t\tgetMidpoint: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getMidpoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );\r\n\r\n\t\t},\r\n\r\n\t\tgetNormal: function ( target ) {\r\n\r\n\t\t\treturn Triangle.getNormal( this.a, this.b, this.c, target );\r\n\r\n\t\t},\r\n\r\n\t\tgetPlane: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getPlane() target is now required' );\r\n\t\t\t\ttarget = new Plane();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.setFromCoplanarPoints( this.a, this.b, this.c );\r\n\r\n\t\t},\r\n\r\n\t\tgetBarycoord: function ( point, target ) {\r\n\r\n\t\t\treturn Triangle.getBarycoord( point, this.a, this.b, this.c, target );\r\n\r\n\t\t},\r\n\r\n\t\tgetUV: function ( point, uv1, uv2, uv3, target ) {\r\n\r\n\t\t\treturn Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn Triangle.containsPoint( point, this.a, this.b, this.c );\r\n\r\n\t\t},\r\n\r\n\t\tisFrontFacing: function ( direction ) {\r\n\r\n\t\t\treturn Triangle.isFrontFacing( this.a, this.b, this.c, direction );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsTriangle( this );\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( p, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar a = this.a, b = this.b, c = this.c;\r\n\t\t\tvar v, w;\r\n\r\n\t\t\t// algorithm thanks to Real-Time Collision Detection by Christer Ericson,\r\n\t\t\t// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,\r\n\t\t\t// under the accompanying license; see chapter 5.1.5 for detailed explanation.\r\n\t\t\t// basically, we're distinguishing which of the voronoi regions of the triangle\r\n\t\t\t// the point lies in with the minimum amount of redundant computation.\r\n\r\n\t\t\t_vab.subVectors( b, a );\r\n\t\t\t_vac.subVectors( c, a );\r\n\t\t\t_vap.subVectors( p, a );\r\n\t\t\tvar d1 = _vab.dot( _vap );\r\n\t\t\tvar d2 = _vac.dot( _vap );\r\n\t\t\tif ( d1 <= 0 && d2 <= 0 ) {\r\n\r\n\t\t\t\t// vertex region of A; barycentric coords (1, 0, 0)\r\n\t\t\t\treturn target.copy( a );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vbp.subVectors( p, b );\r\n\t\t\tvar d3 = _vab.dot( _vbp );\r\n\t\t\tvar d4 = _vac.dot( _vbp );\r\n\t\t\tif ( d3 >= 0 && d4 <= d3 ) {\r\n\r\n\t\t\t\t// vertex region of B; barycentric coords (0, 1, 0)\r\n\t\t\t\treturn target.copy( b );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vc = d1 * d4 - d3 * d2;\r\n\t\t\tif ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {\r\n\r\n\t\t\t\tv = d1 / ( d1 - d3 );\r\n\t\t\t\t// edge region of AB; barycentric coords (1-v, v, 0)\r\n\t\t\t\treturn target.copy( a ).addScaledVector( _vab, v );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vcp.subVectors( p, c );\r\n\t\t\tvar d5 = _vab.dot( _vcp );\r\n\t\t\tvar d6 = _vac.dot( _vcp );\r\n\t\t\tif ( d6 >= 0 && d5 <= d6 ) {\r\n\r\n\t\t\t\t// vertex region of C; barycentric coords (0, 0, 1)\r\n\t\t\t\treturn target.copy( c );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vb = d5 * d2 - d1 * d6;\r\n\t\t\tif ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {\r\n\r\n\t\t\t\tw = d2 / ( d2 - d6 );\r\n\t\t\t\t// edge region of AC; barycentric coords (1-w, 0, w)\r\n\t\t\t\treturn target.copy( a ).addScaledVector( _vac, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar va = d3 * d6 - d5 * d4;\r\n\t\t\tif ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {\r\n\r\n\t\t\t\t_vbc.subVectors( c, b );\r\n\t\t\t\tw = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );\r\n\t\t\t\t// edge region of BC; barycentric coords (0, 1-w, w)\r\n\t\t\t\treturn target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// face region\r\n\t\t\tvar denom = 1 / ( va + vb + vc );\r\n\t\t\t// u = va * denom\r\n\t\t\tv = vb * denom;\r\n\t\t\tw = vc * denom;\r\n\r\n\t\t\treturn target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( triangle ) {\r\n\r\n\t\t\treturn triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,\r\n\t\t'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,\r\n\t\t'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,\r\n\t\t'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,\r\n\t\t'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,\r\n\t\t'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,\r\n\t\t'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,\r\n\t\t'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,\r\n\t\t'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,\r\n\t\t'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,\r\n\t\t'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,\r\n\t\t'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,\r\n\t\t'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,\r\n\t\t'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,\r\n\t\t'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,\r\n\t\t'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,\r\n\t\t'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,\r\n\t\t'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,\r\n\t\t'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,\r\n\t\t'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,\r\n\t\t'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,\r\n\t\t'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,\r\n\t\t'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,\r\n\t\t'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };\r\n\r\n\tvar _hslA = { h: 0, s: 0, l: 0 };\r\n\tvar _hslB = { h: 0, s: 0, l: 0 };\r\n\r\n\tfunction Color( r, g, b ) {\r\n\r\n\t\tif ( g === undefined && b === undefined ) {\r\n\r\n\t\t\t// r is THREE.Color, hex or string\r\n\t\t\treturn this.set( r );\r\n\r\n\t\t}\r\n\r\n\t\treturn this.setRGB( r, g, b );\r\n\r\n\t}\r\n\r\n\tfunction hue2rgb( p, q, t ) {\r\n\r\n\t\tif ( t < 0 ) { t += 1; }\r\n\t\tif ( t > 1 ) { t -= 1; }\r\n\t\tif ( t < 1 / 6 ) { return p + ( q - p ) * 6 * t; }\r\n\t\tif ( t < 1 / 2 ) { return q; }\r\n\t\tif ( t < 2 / 3 ) { return p + ( q - p ) * 6 * ( 2 / 3 - t ); }\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\tfunction SRGBToLinear( c ) {\r\n\r\n\t\treturn ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );\r\n\r\n\t}\r\n\r\n\tfunction LinearToSRGB( c ) {\r\n\r\n\t\treturn ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;\r\n\r\n\t}\r\n\r\n\tObject.assign( Color.prototype, {\r\n\r\n\t\tisColor: true,\r\n\r\n\t\tr: 1, g: 1, b: 1,\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value && value.isColor ) {\r\n\r\n\t\t\t\tthis.copy( value );\r\n\r\n\t\t\t} else if ( typeof value === 'number' ) {\r\n\r\n\t\t\t\tthis.setHex( value );\r\n\r\n\t\t\t} else if ( typeof value === 'string' ) {\r\n\r\n\t\t\t\tthis.setStyle( value );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.r = scalar;\r\n\t\t\tthis.g = scalar;\r\n\t\t\tthis.b = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetHex: function ( hex ) {\r\n\r\n\t\t\thex = Math.floor( hex );\r\n\r\n\t\t\tthis.r = ( hex >> 16 & 255 ) / 255;\r\n\t\t\tthis.g = ( hex >> 8 & 255 ) / 255;\r\n\t\t\tthis.b = ( hex & 255 ) / 255;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRGB: function ( r, g, b ) {\r\n\r\n\t\t\tthis.r = r;\r\n\t\t\tthis.g = g;\r\n\t\t\tthis.b = b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetHSL: function ( h, s, l ) {\r\n\r\n\t\t\t// h,s,l ranges are in 0.0 - 1.0\r\n\t\t\th = _Math.euclideanModulo( h, 1 );\r\n\t\t\ts = _Math.clamp( s, 0, 1 );\r\n\t\t\tl = _Math.clamp( l, 0, 1 );\r\n\r\n\t\t\tif ( s === 0 ) {\r\n\r\n\t\t\t\tthis.r = this.g = this.b = l;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );\r\n\t\t\t\tvar q = ( 2 * l ) - p;\r\n\r\n\t\t\t\tthis.r = hue2rgb( q, p, h + 1 / 3 );\r\n\t\t\t\tthis.g = hue2rgb( q, p, h );\r\n\t\t\t\tthis.b = hue2rgb( q, p, h - 1 / 3 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetStyle: function ( style ) {\r\n\r\n\t\t\tfunction handleAlpha( string ) {\r\n\r\n\t\t\t\tif ( string === undefined ) { return; }\r\n\r\n\t\t\t\tif ( parseFloat( string ) < 1 ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar m;\r\n\r\n\t\t\tif ( m = /^((?:rgb|hsl)a?)\\(\\s*([^\\)]*)\\)/.exec( style ) ) {\r\n\r\n\t\t\t\t// rgb / hsl\r\n\r\n\t\t\t\tvar color;\r\n\t\t\t\tvar name = m[ 1 ];\r\n\t\t\t\tvar components = m[ 2 ];\r\n\r\n\t\t\t\tswitch ( name ) {\r\n\r\n\t\t\t\t\tcase 'rgb':\r\n\t\t\t\t\tcase 'rgba':\r\n\r\n\t\t\t\t\t\tif ( color = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// rgb(255,0,0) rgba(255,0,0,0.5)\r\n\t\t\t\t\t\t\tthis.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;\r\n\t\t\t\t\t\t\tthis.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;\r\n\t\t\t\t\t\t\tthis.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( color = /^(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)\r\n\t\t\t\t\t\t\tthis.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;\r\n\t\t\t\t\t\t\tthis.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;\r\n\t\t\t\t\t\t\tthis.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'hsl':\r\n\t\t\t\t\tcase 'hsla':\r\n\r\n\t\t\t\t\t\tif ( color = /^([0-9]*\\.?[0-9]+)\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// hsl(120,50%,50%) hsla(120,50%,50%,0.5)\r\n\t\t\t\t\t\t\tvar h = parseFloat( color[ 1 ] ) / 360;\r\n\t\t\t\t\t\t\tvar s = parseInt( color[ 2 ], 10 ) / 100;\r\n\t\t\t\t\t\t\tvar l = parseInt( color[ 3 ], 10 ) / 100;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this.setHSL( h, s, l );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( m = /^\\#([A-Fa-f0-9]+)$/.exec( style ) ) {\r\n\r\n\t\t\t\t// hex color\r\n\r\n\t\t\t\tvar hex = m[ 1 ];\r\n\t\t\t\tvar size = hex.length;\r\n\r\n\t\t\t\tif ( size === 3 ) {\r\n\r\n\t\t\t\t\t// #ff0\r\n\t\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;\r\n\t\t\t\t\tthis.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;\r\n\t\t\t\t\tthis.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t} else if ( size === 6 ) {\r\n\r\n\t\t\t\t\t// #ff0000\r\n\t\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;\r\n\t\t\t\t\tthis.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;\r\n\t\t\t\t\tthis.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( style && style.length > 0 ) {\r\n\r\n\t\t\t\treturn this.setColorName( style );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetColorName: function ( style ) {\r\n\r\n\t\t\t// color keywords\r\n\t\t\tvar hex = _colorKeywords[ style ];\r\n\r\n\t\t\tif ( hex !== undefined ) {\r\n\r\n\t\t\t\t// red\r\n\t\t\t\tthis.setHex( hex );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// unknown color\r\n\t\t\t\tconsole.warn( 'THREE.Color: Unknown color ' + style );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.r, this.g, this.b );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( color ) {\r\n\r\n\t\t\tthis.r = color.r;\r\n\t\t\tthis.g = color.g;\r\n\t\t\tthis.b = color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyGammaToLinear: function ( color, gammaFactor ) {\r\n\r\n\t\t\tif ( gammaFactor === undefined ) { gammaFactor = 2.0; }\r\n\r\n\t\t\tthis.r = Math.pow( color.r, gammaFactor );\r\n\t\t\tthis.g = Math.pow( color.g, gammaFactor );\r\n\t\t\tthis.b = Math.pow( color.b, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyLinearToGamma: function ( color, gammaFactor ) {\r\n\r\n\t\t\tif ( gammaFactor === undefined ) { gammaFactor = 2.0; }\r\n\r\n\t\t\tvar safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;\r\n\r\n\t\t\tthis.r = Math.pow( color.r, safeInverse );\r\n\t\t\tthis.g = Math.pow( color.g, safeInverse );\r\n\t\t\tthis.b = Math.pow( color.b, safeInverse );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertGammaToLinear: function ( gammaFactor ) {\r\n\r\n\t\t\tthis.copyGammaToLinear( this, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertLinearToGamma: function ( gammaFactor ) {\r\n\r\n\t\t\tthis.copyLinearToGamma( this, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopySRGBToLinear: function ( color ) {\r\n\r\n\t\t\tthis.r = SRGBToLinear( color.r );\r\n\t\t\tthis.g = SRGBToLinear( color.g );\r\n\t\t\tthis.b = SRGBToLinear( color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyLinearToSRGB: function ( color ) {\r\n\r\n\t\t\tthis.r = LinearToSRGB( color.r );\r\n\t\t\tthis.g = LinearToSRGB( color.g );\r\n\t\t\tthis.b = LinearToSRGB( color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertSRGBToLinear: function () {\r\n\r\n\t\t\tthis.copySRGBToLinear( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertLinearToSRGB: function () {\r\n\r\n\t\t\tthis.copyLinearToSRGB( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetHex: function () {\r\n\r\n\t\t\treturn ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;\r\n\r\n\t\t},\r\n\r\n\t\tgetHexString: function () {\r\n\r\n\t\t\treturn ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );\r\n\r\n\t\t},\r\n\r\n\t\tgetHSL: function ( target ) {\r\n\r\n\t\t\t// h,s,l ranges are in 0.0 - 1.0\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Color: .getHSL() target is now required' );\r\n\t\t\t\ttarget = { h: 0, s: 0, l: 0 };\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar r = this.r, g = this.g, b = this.b;\r\n\r\n\t\t\tvar max = Math.max( r, g, b );\r\n\t\t\tvar min = Math.min( r, g, b );\r\n\r\n\t\t\tvar hue, saturation;\r\n\t\t\tvar lightness = ( min + max ) / 2.0;\r\n\r\n\t\t\tif ( min === max ) {\r\n\r\n\t\t\t\thue = 0;\r\n\t\t\t\tsaturation = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar delta = max - min;\r\n\r\n\t\t\t\tsaturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );\r\n\r\n\t\t\t\tswitch ( max ) {\r\n\r\n\t\t\t\t\tcase r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;\r\n\t\t\t\t\tcase g: hue = ( b - r ) / delta + 2; break;\r\n\t\t\t\t\tcase b: hue = ( r - g ) / delta + 4; break;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\thue /= 6;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.h = hue;\r\n\t\t\ttarget.s = saturation;\r\n\t\t\ttarget.l = lightness;\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetStyle: function () {\r\n\r\n\t\t\treturn 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';\r\n\r\n\t\t},\r\n\r\n\t\toffsetHSL: function ( h, s, l ) {\r\n\r\n\t\t\tthis.getHSL( _hslA );\r\n\r\n\t\t\t_hslA.h += h; _hslA.s += s; _hslA.l += l;\r\n\r\n\t\t\tthis.setHSL( _hslA.h, _hslA.s, _hslA.l );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( color ) {\r\n\r\n\t\t\tthis.r += color.r;\r\n\t\t\tthis.g += color.g;\r\n\t\t\tthis.b += color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddColors: function ( color1, color2 ) {\r\n\r\n\t\t\tthis.r = color1.r + color2.r;\r\n\t\t\tthis.g = color1.g + color2.g;\r\n\t\t\tthis.b = color1.b + color2.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.r += s;\r\n\t\t\tthis.g += s;\r\n\t\t\tthis.b += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( color ) {\r\n\r\n\t\t\tthis.r = Math.max( 0, this.r - color.r );\r\n\t\t\tthis.g = Math.max( 0, this.g - color.g );\r\n\t\t\tthis.b = Math.max( 0, this.b - color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( color ) {\r\n\r\n\t\t\tthis.r *= color.r;\r\n\t\t\tthis.g *= color.g;\r\n\t\t\tthis.b *= color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tthis.r *= s;\r\n\t\t\tthis.g *= s;\r\n\t\t\tthis.b *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( color, alpha ) {\r\n\r\n\t\t\tthis.r += ( color.r - this.r ) * alpha;\r\n\t\t\tthis.g += ( color.g - this.g ) * alpha;\r\n\t\t\tthis.b += ( color.b - this.b ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpHSL: function ( color, alpha ) {\r\n\r\n\t\t\tthis.getHSL( _hslA );\r\n\t\t\tcolor.getHSL( _hslB );\r\n\r\n\t\t\tvar h = _Math.lerp( _hslA.h, _hslB.h, alpha );\r\n\t\t\tvar s = _Math.lerp( _hslA.s, _hslB.s, alpha );\r\n\t\t\tvar l = _Math.lerp( _hslA.l, _hslB.l, alpha );\r\n\r\n\t\t\tthis.setHSL( h, s, l );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( c ) {\r\n\r\n\t\t\treturn ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.r = array[ offset ];\r\n\t\t\tthis.g = array[ offset + 1 ];\r\n\t\t\tthis.b = array[ offset + 2 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.r;\r\n\t\t\tarray[ offset + 1 ] = this.g;\r\n\t\t\tarray[ offset + 2 ] = this.b;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\treturn this.getHex();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tColor.NAMES = _colorKeywords;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Face3( a, b, c, normal, color, materialIndex ) {\r\n\r\n\t\tthis.a = a;\r\n\t\tthis.b = b;\r\n\t\tthis.c = c;\r\n\r\n\t\tthis.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();\r\n\t\tthis.vertexNormals = Array.isArray( normal ) ? normal : [];\r\n\r\n\t\tthis.color = ( color && color.isColor ) ? color : new Color();\r\n\t\tthis.vertexColors = Array.isArray( color ) ? color : [];\r\n\r\n\t\tthis.materialIndex = materialIndex !== undefined ? materialIndex : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Face3.prototype, {\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.a = source.a;\r\n\t\t\tthis.b = source.b;\r\n\t\t\tthis.c = source.c;\r\n\r\n\t\t\tthis.normal.copy( source.normal );\r\n\t\t\tthis.color.copy( source.color );\r\n\r\n\t\t\tthis.materialIndex = source.materialIndex;\r\n\r\n\t\t\tfor ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertexNormals[ i ] = source.vertexNormals[ i ].clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertexColors[ i ] = source.vertexColors[ i ].clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar materialId = 0;\r\n\r\n\tfunction Material() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: materialId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Material';\r\n\r\n\t\tthis.fog = true;\r\n\r\n\t\tthis.blending = NormalBlending;\r\n\t\tthis.side = FrontSide;\r\n\t\tthis.flatShading = false;\r\n\t\tthis.vertexTangents = false;\r\n\t\tthis.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors\r\n\r\n\t\tthis.opacity = 1;\r\n\t\tthis.transparent = false;\r\n\r\n\t\tthis.blendSrc = SrcAlphaFactor;\r\n\t\tthis.blendDst = OneMinusSrcAlphaFactor;\r\n\t\tthis.blendEquation = AddEquation;\r\n\t\tthis.blendSrcAlpha = null;\r\n\t\tthis.blendDstAlpha = null;\r\n\t\tthis.blendEquationAlpha = null;\r\n\r\n\t\tthis.depthFunc = LessEqualDepth;\r\n\t\tthis.depthTest = true;\r\n\t\tthis.depthWrite = true;\r\n\r\n\t\tthis.stencilWriteMask = 0xff;\r\n\t\tthis.stencilFunc = AlwaysStencilFunc;\r\n\t\tthis.stencilRef = 0;\r\n\t\tthis.stencilFuncMask = 0xff;\r\n\t\tthis.stencilFail = KeepStencilOp;\r\n\t\tthis.stencilZFail = KeepStencilOp;\r\n\t\tthis.stencilZPass = KeepStencilOp;\r\n\t\tthis.stencilWrite = false;\r\n\r\n\t\tthis.clippingPlanes = null;\r\n\t\tthis.clipIntersection = false;\r\n\t\tthis.clipShadows = false;\r\n\r\n\t\tthis.shadowSide = null;\r\n\r\n\t\tthis.colorWrite = true;\r\n\r\n\t\tthis.precision = null; // override the renderer's default precision for this material\r\n\r\n\t\tthis.polygonOffset = false;\r\n\t\tthis.polygonOffsetFactor = 0;\r\n\t\tthis.polygonOffsetUnits = 0;\r\n\r\n\t\tthis.dithering = false;\r\n\r\n\t\tthis.alphaTest = 0;\r\n\t\tthis.premultipliedAlpha = false;\r\n\r\n\t\tthis.visible = true;\r\n\r\n\t\tthis.toneMapped = true;\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tMaterial.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Material,\r\n\r\n\t\tisMaterial: true,\r\n\r\n\t\tonBeforeCompile: function () {},\r\n\r\n\t\tsetValues: function ( values ) {\r\n\r\n\t\t\tif ( values === undefined ) { return; }\r\n\r\n\t\t\tfor ( var key in values ) {\r\n\r\n\t\t\t\tvar newValue = values[ key ];\r\n\r\n\t\t\t\tif ( newValue === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.Material: '\" + key + \"' parameter is undefined.\" );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// for backward compatability if shading is set in the constructor\r\n\t\t\t\tif ( key === 'shading' ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\t\t\t\t\tthis.flatShading = ( newValue === FlatShading ) ? true : false;\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar currentValue = this[ key ];\r\n\r\n\t\t\t\tif ( currentValue === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.\" + this.type + \": '\" + key + \"' is not a property of this material.\" );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( currentValue && currentValue.isColor ) {\r\n\r\n\t\t\t\t\tcurrentValue.set( newValue );\r\n\r\n\t\t\t\t} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {\r\n\r\n\t\t\t\t\tcurrentValue.copy( newValue );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis[ key ] = newValue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar isRoot = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tif ( isRoot ) {\r\n\r\n\t\t\t\tmeta = {\r\n\t\t\t\t\ttextures: {},\r\n\t\t\t\t\timages: {}\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Material',\r\n\t\t\t\t\tgenerator: 'Material.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard Material serialization\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\r\n\t\t\tif ( this.color && this.color.isColor ) { data.color = this.color.getHex(); }\r\n\r\n\t\t\tif ( this.roughness !== undefined ) { data.roughness = this.roughness; }\r\n\t\t\tif ( this.metalness !== undefined ) { data.metalness = this.metalness; }\r\n\r\n\t\t\tif ( this.sheen && this.sheen.isColor ) { data.sheen = this.sheen.getHex(); }\r\n\t\t\tif ( this.emissive && this.emissive.isColor ) { data.emissive = this.emissive.getHex(); }\r\n\t\t\tif ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) { data.emissiveIntensity = this.emissiveIntensity; }\r\n\r\n\t\t\tif ( this.specular && this.specular.isColor ) { data.specular = this.specular.getHex(); }\r\n\t\t\tif ( this.shininess !== undefined ) { data.shininess = this.shininess; }\r\n\t\t\tif ( this.clearcoat !== undefined ) { data.clearcoat = this.clearcoat; }\r\n\t\t\tif ( this.clearcoatRoughness !== undefined ) { data.clearcoatRoughness = this.clearcoatRoughness; }\r\n\r\n\t\t\tif ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {\r\n\r\n\t\t\t\tdata.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.clearcoatNormalScale = this.clearcoatNormalScale.toArray();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.map && this.map.isTexture ) { data.map = this.map.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.matcap && this.matcap.isTexture ) { data.matcap = this.matcap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.alphaMap && this.alphaMap.isTexture ) { data.alphaMap = this.alphaMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.lightMap && this.lightMap.isTexture ) { data.lightMap = this.lightMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.aoMap && this.aoMap.isTexture ) {\r\n\r\n\t\t\t\tdata.aoMap = this.aoMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.aoMapIntensity = this.aoMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.bumpMap && this.bumpMap.isTexture ) {\r\n\r\n\t\t\t\tdata.bumpMap = this.bumpMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.bumpScale = this.bumpScale;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.normalMap && this.normalMap.isTexture ) {\r\n\r\n\t\t\t\tdata.normalMap = this.normalMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.normalMapType = this.normalMapType;\r\n\t\t\t\tdata.normalScale = this.normalScale.toArray();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.displacementMap && this.displacementMap.isTexture ) {\r\n\r\n\t\t\t\tdata.displacementMap = this.displacementMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.displacementScale = this.displacementScale;\r\n\t\t\t\tdata.displacementBias = this.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.roughnessMap && this.roughnessMap.isTexture ) { data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.metalnessMap && this.metalnessMap.isTexture ) { data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.emissiveMap && this.emissiveMap.isTexture ) { data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.specularMap && this.specularMap.isTexture ) { data.specularMap = this.specularMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.envMap && this.envMap.isTexture ) {\r\n\r\n\t\t\t\tdata.envMap = this.envMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.reflectivity = this.reflectivity; // Scale behind envMap\r\n\t\t\t\tdata.refractionRatio = this.refractionRatio;\r\n\r\n\t\t\t\tif ( this.combine !== undefined ) { data.combine = this.combine; }\r\n\t\t\t\tif ( this.envMapIntensity !== undefined ) { data.envMapIntensity = this.envMapIntensity; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.gradientMap && this.gradientMap.isTexture ) {\r\n\r\n\t\t\t\tdata.gradientMap = this.gradientMap.toJSON( meta ).uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.size !== undefined ) { data.size = this.size; }\r\n\t\t\tif ( this.sizeAttenuation !== undefined ) { data.sizeAttenuation = this.sizeAttenuation; }\r\n\r\n\t\t\tif ( this.blending !== NormalBlending ) { data.blending = this.blending; }\r\n\t\t\tif ( this.flatShading === true ) { data.flatShading = this.flatShading; }\r\n\t\t\tif ( this.side !== FrontSide ) { data.side = this.side; }\r\n\t\t\tif ( this.vertexColors !== NoColors ) { data.vertexColors = this.vertexColors; }\r\n\r\n\t\t\tif ( this.opacity < 1 ) { data.opacity = this.opacity; }\r\n\t\t\tif ( this.transparent === true ) { data.transparent = this.transparent; }\r\n\r\n\t\t\tdata.depthFunc = this.depthFunc;\r\n\t\t\tdata.depthTest = this.depthTest;\r\n\t\t\tdata.depthWrite = this.depthWrite;\r\n\r\n\t\t\tdata.stencilWrite = this.stencilWrite;\r\n\t\t\tdata.stencilWriteMask = this.stencilWriteMask;\r\n\t\t\tdata.stencilFunc = this.stencilFunc;\r\n\t\t\tdata.stencilRef = this.stencilRef;\r\n\t\t\tdata.stencilFuncMask = this.stencilFuncMask;\r\n\t\t\tdata.stencilFail = this.stencilFail;\r\n\t\t\tdata.stencilZFail = this.stencilZFail;\r\n\t\t\tdata.stencilZPass = this.stencilZPass;\r\n\r\n\t\t\t// rotation (SpriteMaterial)\r\n\t\t\tif ( this.rotation && this.rotation !== 0 ) { data.rotation = this.rotation; }\r\n\r\n\t\t\tif ( this.polygonOffset === true ) { data.polygonOffset = true; }\r\n\t\t\tif ( this.polygonOffsetFactor !== 0 ) { data.polygonOffsetFactor = this.polygonOffsetFactor; }\r\n\t\t\tif ( this.polygonOffsetUnits !== 0 ) { data.polygonOffsetUnits = this.polygonOffsetUnits; }\r\n\r\n\t\t\tif ( this.linewidth && this.linewidth !== 1 ) { data.linewidth = this.linewidth; }\r\n\t\t\tif ( this.dashSize !== undefined ) { data.dashSize = this.dashSize; }\r\n\t\t\tif ( this.gapSize !== undefined ) { data.gapSize = this.gapSize; }\r\n\t\t\tif ( this.scale !== undefined ) { data.scale = this.scale; }\r\n\r\n\t\t\tif ( this.dithering === true ) { data.dithering = true; }\r\n\r\n\t\t\tif ( this.alphaTest > 0 ) { data.alphaTest = this.alphaTest; }\r\n\t\t\tif ( this.premultipliedAlpha === true ) { data.premultipliedAlpha = this.premultipliedAlpha; }\r\n\r\n\t\t\tif ( this.wireframe === true ) { data.wireframe = this.wireframe; }\r\n\t\t\tif ( this.wireframeLinewidth > 1 ) { data.wireframeLinewidth = this.wireframeLinewidth; }\r\n\t\t\tif ( this.wireframeLinecap !== 'round' ) { data.wireframeLinecap = this.wireframeLinecap; }\r\n\t\t\tif ( this.wireframeLinejoin !== 'round' ) { data.wireframeLinejoin = this.wireframeLinejoin; }\r\n\r\n\t\t\tif ( this.morphTargets === true ) { data.morphTargets = true; }\r\n\t\t\tif ( this.morphNormals === true ) { data.morphNormals = true; }\r\n\t\t\tif ( this.skinning === true ) { data.skinning = true; }\r\n\r\n\t\t\tif ( this.visible === false ) { data.visible = false; }\r\n\r\n\t\t\tif ( this.toneMapped === false ) { data.toneMapped = false; }\r\n\r\n\t\t\tif ( JSON.stringify( this.userData ) !== '{}' ) { data.userData = this.userData; }\r\n\r\n\t\t\t// TODO: Copied from Object3D.toJSON\r\n\r\n\t\t\tfunction extractFromCache( cache ) {\r\n\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\tfor ( var key in cache ) {\r\n\r\n\t\t\t\t\tvar data = cache[ key ];\r\n\t\t\t\t\tdelete data.metadata;\r\n\t\t\t\t\tvalues.push( data );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn values;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isRoot ) {\r\n\r\n\t\t\t\tvar textures = extractFromCache( meta.textures );\r\n\t\t\t\tvar images = extractFromCache( meta.images );\r\n\r\n\t\t\t\tif ( textures.length > 0 ) { data.textures = textures; }\r\n\t\t\t\tif ( images.length > 0 ) { data.images = images; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.fog = source.fog;\r\n\r\n\t\t\tthis.blending = source.blending;\r\n\t\t\tthis.side = source.side;\r\n\t\t\tthis.flatShading = source.flatShading;\r\n\t\t\tthis.vertexTangents = source.vertexTangents;\r\n\t\t\tthis.vertexColors = source.vertexColors;\r\n\r\n\t\t\tthis.opacity = source.opacity;\r\n\t\t\tthis.transparent = source.transparent;\r\n\r\n\t\t\tthis.blendSrc = source.blendSrc;\r\n\t\t\tthis.blendDst = source.blendDst;\r\n\t\t\tthis.blendEquation = source.blendEquation;\r\n\t\t\tthis.blendSrcAlpha = source.blendSrcAlpha;\r\n\t\t\tthis.blendDstAlpha = source.blendDstAlpha;\r\n\t\t\tthis.blendEquationAlpha = source.blendEquationAlpha;\r\n\r\n\t\t\tthis.depthFunc = source.depthFunc;\r\n\t\t\tthis.depthTest = source.depthTest;\r\n\t\t\tthis.depthWrite = source.depthWrite;\r\n\r\n\t\t\tthis.stencilWriteMask = source.stencilWriteMask;\r\n\t\t\tthis.stencilFunc = source.stencilFunc;\r\n\t\t\tthis.stencilRef = source.stencilRef;\r\n\t\t\tthis.stencilFuncMask = source.stencilFuncMask;\r\n\t\t\tthis.stencilFail = source.stencilFail;\r\n\t\t\tthis.stencilZFail = source.stencilZFail;\r\n\t\t\tthis.stencilZPass = source.stencilZPass;\r\n\t\t\tthis.stencilWrite = source.stencilWrite;\r\n\r\n\t\t\tvar srcPlanes = source.clippingPlanes,\r\n\t\t\t\tdstPlanes = null;\r\n\r\n\t\t\tif ( srcPlanes !== null ) {\r\n\r\n\t\t\t\tvar n = srcPlanes.length;\r\n\t\t\t\tdstPlanes = new Array( n );\r\n\r\n\t\t\t\tfor ( var i = 0; i !== n; ++ i )\r\n\t\t\t\t\t{ dstPlanes[ i ] = srcPlanes[ i ].clone(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.clippingPlanes = dstPlanes;\r\n\t\t\tthis.clipIntersection = source.clipIntersection;\r\n\t\t\tthis.clipShadows = source.clipShadows;\r\n\r\n\t\t\tthis.shadowSide = source.shadowSide;\r\n\r\n\t\t\tthis.colorWrite = source.colorWrite;\r\n\r\n\t\t\tthis.precision = source.precision;\r\n\r\n\t\t\tthis.polygonOffset = source.polygonOffset;\r\n\t\t\tthis.polygonOffsetFactor = source.polygonOffsetFactor;\r\n\t\t\tthis.polygonOffsetUnits = source.polygonOffsetUnits;\r\n\r\n\t\t\tthis.dithering = source.dithering;\r\n\r\n\t\t\tthis.alphaTest = source.alphaTest;\r\n\t\t\tthis.premultipliedAlpha = source.premultipliedAlpha;\r\n\r\n\t\t\tthis.visible = source.visible;\r\n\r\n\t\t\tthis.toneMapped = source.toneMapped;\r\n\r\n\t\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Material.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.Multiply,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * depthTest: ,\r\n\t * depthWrite: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshBasicMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshBasicMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // emissive\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshBasicMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshBasicMaterial.prototype.constructor = MeshBasicMaterial;\r\n\r\n\tMeshBasicMaterial.prototype.isMeshBasicMaterial = true;\r\n\r\n\tMeshBasicMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _vector$4 = new Vector3();\r\n\r\n\tfunction BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tif ( Array.isArray( array ) ) {\r\n\r\n\t\t\tthrow new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );\r\n\r\n\t\t}\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.array = array;\r\n\t\tthis.itemSize = itemSize;\r\n\t\tthis.count = array !== undefined ? array.length / itemSize : 0;\r\n\t\tthis.normalized = normalized === true;\r\n\r\n\t\tthis.usage = StaticDrawUsage;\r\n\t\tthis.updateRange = { offset: 0, count: - 1 };\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperty( BufferAttribute.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( BufferAttribute.prototype, {\r\n\r\n\t\tisBufferAttribute: true,\r\n\r\n\t\tonUploadCallback: function () {},\r\n\r\n\t\tsetUsage: function ( value ) {\r\n\r\n\t\t\tthis.usage = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\t\t\tthis.array = new source.array.constructor( source.array );\r\n\t\t\tthis.itemSize = source.itemSize;\r\n\t\t\tthis.count = source.count;\r\n\t\t\tthis.normalized = source.normalized;\r\n\r\n\t\t\tthis.usage = source.usage;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyAt: function ( index1, attribute, index2 ) {\r\n\r\n\t\t\tindex1 *= this.itemSize;\r\n\t\t\tindex2 *= attribute.itemSize;\r\n\r\n\t\t\tfor ( var i = 0, l = this.itemSize; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyArray: function ( array ) {\r\n\r\n\t\t\tthis.array.set( array );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyColorsArray: function ( colors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = colors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar color = colors[ i ];\r\n\r\n\t\t\t\tif ( color === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );\r\n\t\t\t\t\tcolor = new Color();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = color.r;\r\n\t\t\t\tarray[ offset ++ ] = color.g;\r\n\t\t\t\tarray[ offset ++ ] = color.b;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector2sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector2();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector3sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector3();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\t\t\t\tarray[ offset ++ ] = vector.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector4sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector4();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\t\t\t\tarray[ offset ++ ] = vector.z;\r\n\t\t\t\tarray[ offset ++ ] = vector.w;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyMatrix3( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyMatrix4( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyNormalMatrix: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyNormalMatrix( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttransformDirection: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.transformDirection( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.array.set( value, offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetX: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize ];\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( index, x ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize ] = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetY: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 1 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( index, y ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetZ: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 2 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( index, z ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetW: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 3 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( index, w ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXY: function ( index, x, y ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZ: function ( index, x, y, z ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\t\t\tthis.array[ index + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZW: function ( index, x, y, z, w ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\t\t\tthis.array[ index + 2 ] = z;\r\n\t\t\tthis.array[ index + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tonUpload: function ( callback ) {\r\n\r\n\t\t\tthis.onUploadCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.array, this.itemSize ).copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\treturn {\r\n\t\t\t\titemSize: this.itemSize,\r\n\t\t\t\ttype: this.array.constructor.name,\r\n\t\t\t\tarray: Array.prototype.slice.call( this.array ),\r\n\t\t\t\tnormalized: this.normalized\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction Int8BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt8BufferAttribute.prototype.constructor = Int8BufferAttribute;\r\n\r\n\r\n\tfunction Uint8BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;\r\n\r\n\r\n\tfunction Uint8ClampedBufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;\r\n\r\n\r\n\tfunction Int16BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt16BufferAttribute.prototype.constructor = Int16BufferAttribute;\r\n\r\n\r\n\tfunction Uint16BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;\r\n\r\n\r\n\tfunction Int32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt32BufferAttribute.prototype.constructor = Int32BufferAttribute;\r\n\r\n\r\n\tfunction Uint32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;\r\n\r\n\r\n\tfunction Float32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tFloat32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tFloat32BufferAttribute.prototype.constructor = Float32BufferAttribute;\r\n\r\n\r\n\tfunction Float64BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tFloat64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tFloat64BufferAttribute.prototype.constructor = Float64BufferAttribute;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction DirectGeometry() {\r\n\r\n\t\tthis.vertices = [];\r\n\t\tthis.normals = [];\r\n\t\tthis.colors = [];\r\n\t\tthis.uvs = [];\r\n\t\tthis.uvs2 = [];\r\n\r\n\t\tthis.groups = [];\r\n\r\n\t\tthis.morphTargets = {};\r\n\r\n\t\tthis.skinWeights = [];\r\n\t\tthis.skinIndices = [];\r\n\r\n\t\t// this.lineDistances = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\t// update flags\r\n\r\n\t\tthis.verticesNeedUpdate = false;\r\n\t\tthis.normalsNeedUpdate = false;\r\n\t\tthis.colorsNeedUpdate = false;\r\n\t\tthis.uvsNeedUpdate = false;\r\n\t\tthis.groupsNeedUpdate = false;\r\n\r\n\t}\r\n\r\n\tObject.assign( DirectGeometry.prototype, {\r\n\r\n\t\tcomputeGroups: function ( geometry ) {\r\n\r\n\t\t\tvar group;\r\n\t\t\tvar groups = [];\r\n\t\t\tvar materialIndex = undefined;\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\r\n\t\t\tfor ( var i = 0; i < faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\t// materials\r\n\r\n\t\t\t\tif ( face.materialIndex !== materialIndex ) {\r\n\r\n\t\t\t\t\tmaterialIndex = face.materialIndex;\r\n\r\n\t\t\t\t\tif ( group !== undefined ) {\r\n\r\n\t\t\t\t\t\tgroup.count = ( i * 3 ) - group.start;\r\n\t\t\t\t\t\tgroups.push( group );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgroup = {\r\n\t\t\t\t\t\tstart: i * 3,\r\n\t\t\t\t\t\tmaterialIndex: materialIndex\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( group !== undefined ) {\r\n\r\n\t\t\t\tgroup.count = ( i * 3 ) - group.start;\r\n\t\t\t\tgroups.push( group );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.groups = groups;\r\n\r\n\t\t},\r\n\r\n\t\tfromGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\t\t\tvar vertices = geometry.vertices;\r\n\t\t\tvar faceVertexUvs = geometry.faceVertexUvs;\r\n\r\n\t\t\tvar hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;\r\n\t\t\tvar hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;\r\n\r\n\t\t\t// morphs\r\n\r\n\t\t\tvar morphTargets = geometry.morphTargets;\r\n\t\t\tvar morphTargetsLength = morphTargets.length;\r\n\r\n\t\t\tvar morphTargetsPosition;\r\n\r\n\t\t\tif ( morphTargetsLength > 0 ) {\r\n\r\n\t\t\t\tmorphTargetsPosition = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < morphTargetsLength; i ++ ) {\r\n\r\n\t\t\t\t\tmorphTargetsPosition[ i ] = {\r\n\t\t\t\t\t\tname: morphTargets[ i ].name,\r\n\t\t\t\t\t \tdata: []\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.position = morphTargetsPosition;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphNormals = geometry.morphNormals;\r\n\t\t\tvar morphNormalsLength = morphNormals.length;\r\n\r\n\t\t\tvar morphTargetsNormal;\r\n\r\n\t\t\tif ( morphNormalsLength > 0 ) {\r\n\r\n\t\t\t\tmorphTargetsNormal = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < morphNormalsLength; i ++ ) {\r\n\r\n\t\t\t\t\tmorphTargetsNormal[ i ] = {\r\n\t\t\t\t\t\tname: morphNormals[ i ].name,\r\n\t\t\t\t\t \tdata: []\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.normal = morphTargetsNormal;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skins\r\n\r\n\t\t\tvar skinIndices = geometry.skinIndices;\r\n\t\t\tvar skinWeights = geometry.skinWeights;\r\n\r\n\t\t\tvar hasSkinIndices = skinIndices.length === vertices.length;\r\n\t\t\tvar hasSkinWeights = skinWeights.length === vertices.length;\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( vertices.length > 0 && faces.length === 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tthis.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tthis.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvar normal = face.normal;\r\n\r\n\t\t\t\t\tthis.normals.push( normal, normal, normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar vertexColors = face.vertexColors;\r\n\r\n\t\t\t\tif ( vertexColors.length === 3 ) {\r\n\r\n\t\t\t\t\tthis.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvar color = face.color;\r\n\r\n\t\t\t\t\tthis.colors.push( color, color, color );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexUv === true ) {\r\n\r\n\t\t\t\t\tvar vertexUvs = faceVertexUvs[ 0 ][ i ];\r\n\r\n\t\t\t\t\tif ( vertexUvs !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );\r\n\r\n\t\t\t\t\t\tthis.uvs.push( new Vector2(), new Vector2(), new Vector2() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexUv2 === true ) {\r\n\r\n\t\t\t\t\tvar vertexUvs = faceVertexUvs[ 1 ][ i ];\r\n\r\n\t\t\t\t\tif ( vertexUvs !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );\r\n\r\n\t\t\t\t\t\tthis.uvs2.push( new Vector2(), new Vector2(), new Vector2() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// morphs\r\n\r\n\t\t\t\tfor ( var j = 0; j < morphTargetsLength; j ++ ) {\r\n\r\n\t\t\t\t\tvar morphTarget = morphTargets[ j ].vertices;\r\n\r\n\t\t\t\t\tmorphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var j = 0; j < morphNormalsLength; j ++ ) {\r\n\r\n\t\t\t\t\tvar morphNormal = morphNormals[ j ].vertexNormals[ i ];\r\n\r\n\t\t\t\t\tmorphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// skins\r\n\r\n\t\t\t\tif ( hasSkinIndices ) {\r\n\r\n\t\t\t\t\tthis.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasSkinWeights ) {\r\n\r\n\t\t\t\t\tthis.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.computeGroups( geometry );\r\n\r\n\t\t\tthis.verticesNeedUpdate = geometry.verticesNeedUpdate;\r\n\t\t\tthis.normalsNeedUpdate = geometry.normalsNeedUpdate;\r\n\t\t\tthis.colorsNeedUpdate = geometry.colorsNeedUpdate;\r\n\t\t\tthis.uvsNeedUpdate = geometry.uvsNeedUpdate;\r\n\t\t\tthis.groupsNeedUpdate = geometry.groupsNeedUpdate;\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction arrayMax( array ) {\r\n\r\n\t\tif ( array.length === 0 ) { return - Infinity; }\r\n\r\n\t\tvar max = array[ 0 ];\r\n\r\n\t\tfor ( var i = 1, l = array.length; i < l; ++ i ) {\r\n\r\n\t\t\tif ( array[ i ] > max ) { max = array[ i ]; }\r\n\r\n\t\t}\r\n\r\n\t\treturn max;\r\n\r\n\t}\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id\r\n\r\n\tvar _m1$2 = new Matrix4();\r\n\tvar _obj = new Object3D();\r\n\tvar _offset = new Vector3();\r\n\tvar _box$2 = new Box3();\r\n\tvar _boxMorphTargets = new Box3();\r\n\tvar _vector$5 = new Vector3();\r\n\r\n\tfunction BufferGeometry() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'BufferGeometry';\r\n\r\n\t\tthis.index = null;\r\n\t\tthis.attributes = {};\r\n\r\n\t\tthis.morphAttributes = {};\r\n\t\tthis.morphTargetsRelative = false;\r\n\r\n\t\tthis.groups = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\tthis.drawRange = { start: 0, count: Infinity };\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t}\r\n\r\n\tBufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: BufferGeometry,\r\n\r\n\t\tisBufferGeometry: true,\r\n\r\n\t\tgetIndex: function () {\r\n\r\n\t\t\treturn this.index;\r\n\r\n\t\t},\r\n\r\n\t\tsetIndex: function ( index ) {\r\n\r\n\t\t\tif ( Array.isArray( index ) ) {\r\n\r\n\t\t\t\tthis.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.index = index;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tgetAttribute: function ( name ) {\r\n\r\n\t\t\treturn this.attributes[ name ];\r\n\r\n\t\t},\r\n\r\n\t\tsetAttribute: function ( name, attribute ) {\r\n\r\n\t\t\tthis.attributes[ name ] = attribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdeleteAttribute: function ( name ) {\r\n\r\n\t\t\tdelete this.attributes[ name ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddGroup: function ( start, count, materialIndex ) {\r\n\r\n\t\t\tthis.groups.push( {\r\n\r\n\t\t\t\tstart: start,\r\n\t\t\t\tcount: count,\r\n\t\t\t\tmaterialIndex: materialIndex !== undefined ? materialIndex : 0\r\n\r\n\t\t\t} );\r\n\r\n\t\t},\r\n\r\n\t\tclearGroups: function () {\r\n\r\n\t\t\tthis.groups = [];\r\n\r\n\t\t},\r\n\r\n\t\tsetDrawRange: function ( start, count ) {\r\n\r\n\t\t\tthis.drawRange.start = start;\r\n\t\t\tthis.drawRange.count = count;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\r\n\t\t\tif ( position !== undefined ) {\r\n\r\n\t\t\t\tmatrix.applyToBufferAttribute( position );\r\n\t\t\t\tposition.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar normal = this.attributes.normal;\r\n\r\n\t\t\tif ( normal !== undefined ) {\r\n\r\n\t\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\t\tnormal.applyNormalMatrix( normalMatrix );\r\n\r\n\t\t\t\tnormal.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar tangent = this.attributes.tangent;\r\n\r\n\t\t\tif ( tangent !== undefined ) {\r\n\r\n\t\t\t\ttangent.transformDirection( matrix );\r\n\r\n\t\t\t\ttangent.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world x-axis\r\n\r\n\t\t\t_m1$2.makeRotationX( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world y-axis\r\n\r\n\t\t\t_m1$2.makeRotationY( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world z-axis\r\n\r\n\t\t\t_m1$2.makeRotationZ( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( x, y, z ) {\r\n\r\n\t\t\t// translate geometry\r\n\r\n\t\t\t_m1$2.makeTranslation( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( x, y, z ) {\r\n\r\n\t\t\t// scale geometry\r\n\r\n\t\t\t_m1$2.makeScale( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( vector ) {\r\n\r\n\t\t\t_obj.lookAt( vector );\r\n\r\n\t\t\t_obj.updateMatrix();\r\n\r\n\t\t\tthis.applyMatrix( _obj.matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function () {\r\n\r\n\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\tthis.boundingBox.getCenter( _offset ).negate();\r\n\r\n\t\t\tthis.translate( _offset.x, _offset.y, _offset.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromObject: function ( object ) {\r\n\r\n\t\t\t// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( object.isPoints || object.isLine ) {\r\n\r\n\t\t\t\tvar positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );\r\n\t\t\t\tvar colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );\r\n\r\n\t\t\t\tthis.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );\r\n\t\t\t\tthis.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );\r\n\r\n\t\t\t\tif ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {\r\n\r\n\t\t\t\t\tvar lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );\r\n\r\n\t\t\t\t\tthis.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isMesh ) {\r\n\r\n\t\t\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\t\t\tthis.fromGeometry( geometry );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tvar position = [];\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tposition.push( point.x, point.y, point.z || 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateFromObject: function ( object ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( object.isMesh ) {\r\n\r\n\t\t\t\tvar direct = geometry.__directGeometry;\r\n\r\n\t\t\t\tif ( geometry.elementsNeedUpdate === true ) {\r\n\r\n\t\t\t\t\tdirect = undefined;\r\n\t\t\t\t\tgeometry.elementsNeedUpdate = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( direct === undefined ) {\r\n\r\n\t\t\t\t\treturn this.fromGeometry( geometry );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdirect.verticesNeedUpdate = geometry.verticesNeedUpdate;\r\n\t\t\t\tdirect.normalsNeedUpdate = geometry.normalsNeedUpdate;\r\n\t\t\t\tdirect.colorsNeedUpdate = geometry.colorsNeedUpdate;\r\n\t\t\t\tdirect.uvsNeedUpdate = geometry.uvsNeedUpdate;\r\n\t\t\t\tdirect.groupsNeedUpdate = geometry.groupsNeedUpdate;\r\n\r\n\t\t\t\tgeometry.verticesNeedUpdate = false;\r\n\t\t\t\tgeometry.normalsNeedUpdate = false;\r\n\t\t\t\tgeometry.colorsNeedUpdate = false;\r\n\t\t\t\tgeometry.uvsNeedUpdate = false;\r\n\t\t\t\tgeometry.groupsNeedUpdate = false;\r\n\r\n\t\t\t\tgeometry = direct;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute;\r\n\r\n\t\t\tif ( geometry.verticesNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.position;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector3sArray( geometry.vertices );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.verticesNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.normalsNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.normal;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector3sArray( geometry.normals );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.normalsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.colorsNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.color;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyColorsArray( geometry.colors );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.colorsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvsNeedUpdate ) {\r\n\r\n\t\t\t\tattribute = this.attributes.uv;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector2sArray( geometry.uvs );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.uvsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.lineDistancesNeedUpdate ) {\r\n\r\n\t\t\t\tattribute = this.attributes.lineDistance;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyArray( geometry.lineDistances );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.lineDistancesNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.groupsNeedUpdate ) {\r\n\r\n\t\t\t\tgeometry.computeGroups( object.geometry );\r\n\t\t\t\tthis.groups = geometry.groups;\r\n\r\n\t\t\t\tgeometry.groupsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tfromGeometry: function ( geometry ) {\r\n\r\n\t\t\tgeometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );\r\n\r\n\t\t\treturn this.fromDirectGeometry( geometry.__directGeometry );\r\n\r\n\t\t},\r\n\r\n\t\tfromDirectGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar positions = new Float32Array( geometry.vertices.length * 3 );\r\n\t\t\tthis.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );\r\n\r\n\t\t\tif ( geometry.normals.length > 0 ) {\r\n\r\n\t\t\t\tvar normals = new Float32Array( geometry.normals.length * 3 );\r\n\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.colors.length > 0 ) {\r\n\r\n\t\t\t\tvar colors = new Float32Array( geometry.colors.length * 3 );\r\n\t\t\t\tthis.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvs.length > 0 ) {\r\n\r\n\t\t\t\tvar uvs = new Float32Array( geometry.uvs.length * 2 );\r\n\t\t\t\tthis.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvs2.length > 0 ) {\r\n\r\n\t\t\t\tvar uvs2 = new Float32Array( geometry.uvs2.length * 2 );\r\n\t\t\t\tthis.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tthis.groups = geometry.groups;\r\n\r\n\t\t\t// morphs\r\n\r\n\t\t\tfor ( var name in geometry.morphTargets ) {\r\n\r\n\t\t\t\tvar array = [];\r\n\t\t\t\tvar morphTargets = geometry.morphTargets[ name ];\r\n\r\n\t\t\t\tfor ( var i = 0, l = morphTargets.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar morphTarget = morphTargets[ i ];\r\n\r\n\t\t\t\t\tvar attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );\r\n\t\t\t\t\tattribute.name = morphTarget.name;\r\n\r\n\t\t\t\t\tarray.push( attribute.copyVector3sArray( morphTarget.data ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphAttributes[ name ] = array;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skinning\r\n\r\n\t\t\tif ( geometry.skinIndices.length > 0 ) {\r\n\r\n\t\t\t\tvar skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );\r\n\t\t\t\tthis.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.skinWeights.length > 0 ) {\r\n\r\n\t\t\t\tvar skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );\r\n\t\t\t\tthis.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingBox: function () {\r\n\r\n\t\t\tif ( this.boundingBox === null ) {\r\n\r\n\t\t\t\tthis.boundingBox = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\t\t\tvar morphAttributesPosition = this.morphAttributes.position;\r\n\r\n\t\t\tif ( position !== undefined ) {\r\n\r\n\t\t\t\tthis.boundingBox.setFromBufferAttribute( position );\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\t_box$2.setFromBufferAttribute( morphAttribute );\r\n\r\n\t\t\t\t\t\tif ( this.morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( this.boundingBox.min, _box$2.min );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( this.boundingBox.max, _box$2.max );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box$2.min );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box$2.max );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.boundingBox.makeEmpty();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The \"position\" attribute is likely to have NaN values.', this );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingSphere: function () {\r\n\r\n\t\t\tif ( this.boundingSphere === null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = new Sphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\t\t\tvar morphAttributesPosition = this.morphAttributes.position;\r\n\r\n\t\t\tif ( position ) {\r\n\r\n\t\t\t\t// first, find the center of the bounding sphere\r\n\r\n\t\t\t\tvar center = this.boundingSphere.center;\r\n\r\n\t\t\t\t_box$2.setFromBufferAttribute( position );\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\t_boxMorphTargets.setFromBufferAttribute( morphAttribute );\r\n\r\n\t\t\t\t\t\tif ( this.morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( _box$2.min, _boxMorphTargets.min );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( _box$2.max, _boxMorphTargets.max );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _boxMorphTargets.min );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _boxMorphTargets.max );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_box$2.getCenter( center );\r\n\r\n\t\t\t\t// second, try to find a boundingSphere with a radius smaller than the\r\n\t\t\t\t// boundingSphere of the boundingBox: sqrt(3) smaller in the best case\r\n\r\n\t\t\t\tvar maxRadiusSq = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, il = position.count; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t_vector$5.fromBufferAttribute( position, i );\r\n\r\n\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$5 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\tvar morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.fromBufferAttribute( morphAttribute, j );\r\n\r\n\t\t\t\t\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t\t_offset.fromBufferAttribute( position, j );\r\n\t\t\t\t\t\t\t\t_vector$5.add( _offset );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$5 ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.boundingSphere.radius = Math.sqrt( maxRadiusSq );\r\n\r\n\t\t\t\tif ( isNaN( this.boundingSphere.radius ) ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The \"position\" attribute is likely to have NaN values.', this );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFaceNormals: function () {\r\n\r\n\t\t\t// backwards compatibility\r\n\r\n\t\t},\r\n\r\n\t\tcomputeVertexNormals: function () {\r\n\r\n\t\t\tvar index = this.index;\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tif ( attributes.position ) {\r\n\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( attributes.normal === undefined ) {\r\n\r\n\t\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// reset existing normals to zero\r\n\r\n\t\t\t\t\tvar array = attributes.normal.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tarray[ i ] = 0;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar normals = attributes.normal.array;\r\n\r\n\t\t\t\tvar vA, vB, vC;\r\n\t\t\t\tvar pA = new Vector3(), pB = new Vector3(), pC = new Vector3();\r\n\t\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\t\t// indexed elements\r\n\r\n\t\t\t\tif ( index ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = index.count; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\tvA = indices[ i + 0 ] * 3;\r\n\t\t\t\t\t\tvB = indices[ i + 1 ] * 3;\r\n\t\t\t\t\t\tvC = indices[ i + 2 ] * 3;\r\n\r\n\t\t\t\t\t\tpA.fromArray( positions, vA );\r\n\t\t\t\t\t\tpB.fromArray( positions, vB );\r\n\t\t\t\t\t\tpC.fromArray( positions, vC );\r\n\r\n\t\t\t\t\t\tcb.subVectors( pC, pB );\r\n\t\t\t\t\t\tab.subVectors( pA, pB );\r\n\t\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\t\tnormals[ vA ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vA + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vA + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ vB ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vB + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vB + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ vC ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vC + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vC + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// non-indexed elements (unconnected triangle soup)\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = positions.length; i < il; i += 9 ) {\r\n\r\n\t\t\t\t\t\tpA.fromArray( positions, i );\r\n\t\t\t\t\t\tpB.fromArray( positions, i + 3 );\r\n\t\t\t\t\t\tpC.fromArray( positions, i + 6 );\r\n\r\n\t\t\t\t\t\tcb.subVectors( pC, pB );\r\n\t\t\t\t\t\tab.subVectors( pA, pB );\r\n\t\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\t\tnormals[ i ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 1 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 2 ] = cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ i + 3 ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 4 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 5 ] = cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ i + 6 ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 7 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 8 ] = cb.z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.normalizeNormals();\r\n\r\n\t\t\t\tattributes.normal.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tmerge: function ( geometry, offset ) {\r\n\r\n\t\t\tif ( ! ( geometry && geometry.isBufferGeometry ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( offset === undefined ) {\r\n\r\n\t\t\t\toffset = 0;\r\n\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '\r\n\t\t\t\t\t+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'\r\n\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tif ( geometry.attributes[ key ] === undefined ) { continue; }\r\n\r\n\t\t\t\tvar attribute1 = attributes[ key ];\r\n\t\t\t\tvar attributeArray1 = attribute1.array;\r\n\r\n\t\t\t\tvar attribute2 = geometry.attributes[ key ];\r\n\t\t\t\tvar attributeArray2 = attribute2.array;\r\n\r\n\t\t\t\tvar attributeOffset = attribute2.itemSize * offset;\r\n\t\t\t\tvar length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );\r\n\r\n\t\t\t\tfor ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {\r\n\r\n\t\t\t\t\tattributeArray1[ j ] = attributeArray2[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalizeNormals: function () {\r\n\r\n\t\t\tvar normals = this.attributes.normal;\r\n\r\n\t\t\tfor ( var i = 0, il = normals.count; i < il; i ++ ) {\r\n\r\n\t\t\t\t_vector$5.x = normals.getX( i );\r\n\t\t\t\t_vector$5.y = normals.getY( i );\r\n\t\t\t\t_vector$5.z = normals.getZ( i );\r\n\r\n\t\t\t\t_vector$5.normalize();\r\n\r\n\t\t\t\tnormals.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoNonIndexed: function () {\r\n\r\n\t\t\tfunction convertBufferAttribute( attribute, indices ) {\r\n\r\n\t\t\t\tvar array = attribute.array;\r\n\t\t\t\tvar itemSize = attribute.itemSize;\r\n\r\n\t\t\t\tvar array2 = new array.constructor( indices.length * itemSize );\r\n\r\n\t\t\t\tvar index = 0, index2 = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, l = indices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tindex = indices[ i ] * itemSize;\r\n\r\n\t\t\t\t\tfor ( var j = 0; j < itemSize; j ++ ) {\r\n\r\n\t\t\t\t\t\tarray2[ index2 ++ ] = array[ index ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn new BufferAttribute( array2, itemSize );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.index === null ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar geometry2 = new BufferGeometry();\r\n\r\n\t\t\tvar indices = this.index.array;\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\t// attributes\r\n\r\n\t\t\tfor ( var name in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ name ];\r\n\r\n\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\r\n\r\n\t\t\t\tgeometry2.setAttribute( name, newAttribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph attributes\r\n\r\n\t\t\tvar morphAttributes = this.morphAttributes;\r\n\r\n\t\t\tfor ( name in morphAttributes ) {\r\n\r\n\t\t\t\tvar morphArray = [];\r\n\t\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\r\n\r\n\t\t\t\tfor ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar attribute = morphAttribute[ i ];\r\n\r\n\t\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\r\n\r\n\t\t\t\t\tmorphArray.push( newAttribute );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry2.morphAttributes[ name ] = morphArray;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry2.morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tvar groups = this.groups;\r\n\r\n\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\tgeometry2.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometry2;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'BufferGeometry',\r\n\t\t\t\t\tgenerator: 'BufferGeometry.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard BufferGeometry serialization\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\t\t\tif ( Object.keys( this.userData ).length > 0 ) { data.userData = this.userData; }\r\n\r\n\t\t\tif ( this.parameters !== undefined ) {\r\n\r\n\t\t\t\tvar parameters = this.parameters;\r\n\r\n\t\t\t\tfor ( var key in parameters ) {\r\n\r\n\t\t\t\t\tif ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn data;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdata.data = { attributes: {} };\r\n\r\n\t\t\tvar index = this.index;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tdata.data.index = {\r\n\t\t\t\t\ttype: index.array.constructor.name,\r\n\t\t\t\t\tarray: Array.prototype.slice.call( index.array )\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ key ];\r\n\r\n\t\t\t\tvar attributeData = attribute.toJSON();\r\n\r\n\t\t\t\tif ( attribute.name !== '' ) { attributeData.name = attribute.name; }\r\n\r\n\t\t\t\tdata.data.attributes[ key ] = attributeData;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphAttributes = {};\r\n\t\t\tvar hasMorphAttributes = false;\r\n\r\n\t\t\tfor ( var key in this.morphAttributes ) {\r\n\r\n\t\t\t\tvar attributeArray = this.morphAttributes[ key ];\r\n\r\n\t\t\t\tvar array = [];\r\n\r\n\t\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar attribute = attributeArray[ i ];\r\n\r\n\t\t\t\t\tvar attributeData = attribute.toJSON();\r\n\r\n\t\t\t\t\tif ( attribute.name !== '' ) { attributeData.name = attribute.name; }\r\n\r\n\t\t\t\t\tarray.push( attributeData );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( array.length > 0 ) {\r\n\r\n\t\t\t\t\tmorphAttributes[ key ] = array;\r\n\r\n\t\t\t\t\thasMorphAttributes = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( hasMorphAttributes ) {\r\n\r\n\t\t\t\tdata.data.morphAttributes = morphAttributes;\r\n\t\t\t\tdata.data.morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = this.groups;\r\n\r\n\t\t\tif ( groups.length > 0 ) {\r\n\r\n\t\t\t\tdata.data.groups = JSON.parse( JSON.stringify( groups ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundingSphere = this.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tdata.data.boundingSphere = {\r\n\t\t\t\t\tcenter: boundingSphere.center.toArray(),\r\n\t\t\t\t\tradius: boundingSphere.radius\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\t/*\r\n\t\t\t // Handle primitives\r\n\r\n\t\t\t var parameters = this.parameters;\r\n\r\n\t\t\t if ( parameters !== undefined ) {\r\n\r\n\t\t\t var values = [];\r\n\r\n\t\t\t for ( var key in parameters ) {\r\n\r\n\t\t\t values.push( parameters[ key ] );\r\n\r\n\t\t\t }\r\n\r\n\t\t\t var geometry = Object.create( this.constructor.prototype );\r\n\t\t\t this.constructor.apply( geometry, values );\r\n\t\t\t return geometry;\r\n\r\n\t\t\t }\r\n\r\n\t\t\t return new this.constructor().copy( this );\r\n\t\t\t */\r\n\r\n\t\t\treturn new BufferGeometry().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tvar name, i, l;\r\n\r\n\t\t\t// reset\r\n\r\n\t\t\tthis.index = null;\r\n\t\t\tthis.attributes = {};\r\n\t\t\tthis.morphAttributes = {};\r\n\t\t\tthis.groups = [];\r\n\t\t\tthis.boundingBox = null;\r\n\t\t\tthis.boundingSphere = null;\r\n\r\n\t\t\t// name\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\t// index\r\n\r\n\t\t\tvar index = source.index;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tthis.setIndex( index.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// attributes\r\n\r\n\t\t\tvar attributes = source.attributes;\r\n\r\n\t\t\tfor ( name in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ name ];\r\n\t\t\t\tthis.setAttribute( name, attribute.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph attributes\r\n\r\n\t\t\tvar morphAttributes = source.morphAttributes;\r\n\r\n\t\t\tfor ( name in morphAttributes ) {\r\n\r\n\t\t\t\tvar array = [];\r\n\t\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\r\n\r\n\t\t\t\tfor ( i = 0, l = morphAttribute.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tarray.push( morphAttribute[ i ].clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphAttributes[ name ] = array;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.morphTargetsRelative = source.morphTargetsRelative;\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tvar groups = source.groups;\r\n\r\n\t\t\tfor ( i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\tthis.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding box\r\n\r\n\t\t\tvar boundingBox = source.boundingBox;\r\n\r\n\t\t\tif ( boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding sphere\r\n\r\n\t\t\tvar boundingSphere = source.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// draw range\r\n\r\n\t\t\tthis.drawRange.start = source.drawRange.start;\r\n\t\t\tthis.drawRange.count = source.drawRange.count;\r\n\r\n\t\t\t// user data\r\n\r\n\t\t\tthis.userData = source.userData;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author jonobr1 / http://jonobr1.com/\r\n\t */\r\n\r\n\tvar _inverseMatrix = new Matrix4();\r\n\tvar _ray = new Ray();\r\n\tvar _sphere = new Sphere();\r\n\r\n\tvar _vA = new Vector3();\r\n\tvar _vB = new Vector3();\r\n\tvar _vC = new Vector3();\r\n\r\n\tvar _tempA = new Vector3();\r\n\tvar _tempB = new Vector3();\r\n\tvar _tempC = new Vector3();\r\n\r\n\tvar _morphA = new Vector3();\r\n\tvar _morphB = new Vector3();\r\n\tvar _morphC = new Vector3();\r\n\r\n\tvar _uvA = new Vector2();\r\n\tvar _uvB = new Vector2();\r\n\tvar _uvC = new Vector2();\r\n\r\n\tvar _intersectionPoint = new Vector3();\r\n\tvar _intersectionPointWorld = new Vector3();\r\n\r\n\tfunction Mesh( geometry, material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Mesh';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t\tthis.updateMorphTargets();\r\n\r\n\t}\r\n\r\n\tMesh.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Mesh,\r\n\r\n\t\tisMesh: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tif ( source.morphTargetInfluences !== undefined ) {\r\n\r\n\t\t\t\tthis.morphTargetInfluences = source.morphTargetInfluences.slice();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( source.morphTargetDictionary !== undefined ) {\r\n\r\n\t\t\t\tthis.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar m, ml, name;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\t\t\t\tvar keys = Object.keys( morphAttributes );\r\n\r\n\t\t\t\tif ( keys.length > 0 ) {\r\n\r\n\t\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\r\n\r\n\t\t\t\t\tif ( morphAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.morphTargetInfluences = [];\r\n\t\t\t\t\t\tthis.morphTargetDictionary = {};\r\n\r\n\t\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\r\n\r\n\t\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\r\n\r\n\t\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\r\n\t\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar morphTargets = geometry.morphTargets;\r\n\r\n\t\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar material = this.material;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\r\n\t\t\tif ( material === undefined ) { return; }\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere.copy( geometry.boundingSphere );\r\n\t\t\t_sphere.applyMatrix4( matrixWorld );\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix.getInverse( matrixWorld );\r\n\t\t\t_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );\r\n\r\n\t\t\t// Check boundingBox before continuing\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tif ( _ray.intersectsBox( geometry.boundingBox ) === false ) { return; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar intersection;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar a, b, c;\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar position = geometry.attributes.position;\r\n\t\t\t\tvar morphPosition = geometry.morphAttributes.position;\r\n\t\t\t\tvar morphTargetsRelative = geometry.morphTargetsRelative;\r\n\t\t\t\tvar uv = geometry.attributes.uv;\r\n\t\t\t\tvar uv2 = geometry.attributes.uv2;\r\n\t\t\t\tvar groups = geometry.groups;\r\n\t\t\t\tvar drawRange = geometry.drawRange;\r\n\t\t\t\tvar i, j, il, jl;\r\n\t\t\t\tvar group, groupMaterial;\r\n\t\t\t\tvar start, end;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\t// indexed buffer geometry\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tgroup = groups[ i ];\r\n\t\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\r\n\t\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\ta = index.getX( j );\r\n\t\t\t\t\t\t\t\tb = index.getX( j + 1 );\r\n\t\t\t\t\t\t\t\tc = index.getX( j + 2 );\r\n\r\n\t\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics\r\n\t\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\r\n\t\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstart = Math.max( 0, drawRange.start );\r\n\t\t\t\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\ta = index.getX( i );\r\n\t\t\t\t\t\t\tb = index.getX( i + 1 );\r\n\t\t\t\t\t\t\tc = index.getX( i + 2 );\r\n\r\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics\r\n\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( position !== undefined ) {\r\n\r\n\t\t\t\t\t// non-indexed buffer geometry\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tgroup = groups[ i ];\r\n\t\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\r\n\t\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\ta = j;\r\n\t\t\t\t\t\t\t\tb = j + 1;\r\n\t\t\t\t\t\t\t\tc = j + 2;\r\n\r\n\t\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics\r\n\t\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\r\n\t\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstart = Math.max( 0, drawRange.start );\r\n\t\t\t\t\t\tend = Math.min( position.count, ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\ta = i;\r\n\t\t\t\t\t\t\tb = i + 1;\r\n\t\t\t\t\t\t\tc = i + 2;\r\n\r\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics\r\n\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar fvA, fvB, fvC;\r\n\t\t\t\tvar isMultiMaterial = Array.isArray( material );\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar faces = geometry.faces;\r\n\t\t\t\tvar uvs;\r\n\r\n\t\t\t\tvar faceVertexUvs = geometry.faceVertexUvs[ 0 ];\r\n\t\t\t\tif ( faceVertexUvs.length > 0 ) { uvs = faceVertexUvs; }\r\n\r\n\t\t\t\tfor ( var f = 0, fl = faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tvar face = faces[ f ];\r\n\t\t\t\t\tvar faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;\r\n\r\n\t\t\t\t\tif ( faceMaterial === undefined ) { continue; }\r\n\r\n\t\t\t\t\tfvA = vertices[ face.a ];\r\n\t\t\t\t\tfvB = vertices[ face.b ];\r\n\t\t\t\t\tfvC = vertices[ face.c ];\r\n\r\n\t\t\t\t\tintersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );\r\n\r\n\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\tif ( uvs && uvs[ f ] ) {\r\n\r\n\t\t\t\t\t\t\tvar uvs_f = uvs[ f ];\r\n\t\t\t\t\t\t\t_uvA.copy( uvs_f[ 0 ] );\r\n\t\t\t\t\t\t\t_uvB.copy( uvs_f[ 1 ] );\r\n\t\t\t\t\t\t\t_uvC.copy( uvs_f[ 2 ] );\r\n\r\n\t\t\t\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tintersection.face = face;\r\n\t\t\t\t\t\tintersection.faceIndex = f;\r\n\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {\r\n\r\n\t\tvar intersect;\r\n\r\n\t\tif ( material.side === BackSide ) {\r\n\r\n\t\t\tintersect = ray.intersectTriangle( pC, pB, pA, true, point );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tintersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );\r\n\r\n\t\t}\r\n\r\n\t\tif ( intersect === null ) { return null; }\r\n\r\n\t\t_intersectionPointWorld.copy( point );\r\n\t\t_intersectionPointWorld.applyMatrix4( object.matrixWorld );\r\n\r\n\t\tvar distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );\r\n\r\n\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return null; }\r\n\r\n\t\treturn {\r\n\t\t\tdistance: distance,\r\n\t\t\tpoint: _intersectionPointWorld.clone(),\r\n\t\t\tobject: object\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {\r\n\r\n\t\t_vA.fromBufferAttribute( position, a );\r\n\t\t_vB.fromBufferAttribute( position, b );\r\n\t\t_vC.fromBufferAttribute( position, c );\r\n\r\n\t\tvar morphInfluences = object.morphTargetInfluences;\r\n\r\n\t\tif ( material.morphTargets && morphPosition && morphInfluences ) {\r\n\r\n\t\t\t_morphA.set( 0, 0, 0 );\r\n\t\t\t_morphB.set( 0, 0, 0 );\r\n\t\t\t_morphC.set( 0, 0, 0 );\r\n\r\n\t\t\tfor ( var i = 0, il = morphPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar influence = morphInfluences[ i ];\r\n\t\t\t\tvar morphAttribute = morphPosition[ i ];\r\n\r\n\t\t\t\tif ( influence === 0 ) { continue; }\r\n\r\n\t\t\t\t_tempA.fromBufferAttribute( morphAttribute, a );\r\n\t\t\t\t_tempB.fromBufferAttribute( morphAttribute, b );\r\n\t\t\t\t_tempC.fromBufferAttribute( morphAttribute, c );\r\n\r\n\t\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t_morphA.addScaledVector( _tempA, influence );\r\n\t\t\t\t\t_morphB.addScaledVector( _tempB, influence );\r\n\t\t\t\t\t_morphC.addScaledVector( _tempC, influence );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\r\n\t\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\r\n\t\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vA.add( _morphA );\r\n\t\t\t_vB.add( _morphB );\r\n\t\t\t_vC.add( _morphC );\r\n\r\n\t\t}\r\n\r\n\t\tvar intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );\r\n\r\n\t\tif ( intersection ) {\r\n\r\n\t\t\tif ( uv ) {\r\n\r\n\t\t\t\t_uvA.fromBufferAttribute( uv, a );\r\n\t\t\t\t_uvB.fromBufferAttribute( uv, b );\r\n\t\t\t\t_uvC.fromBufferAttribute( uv, c );\r\n\r\n\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv2 ) {\r\n\r\n\t\t\t\t_uvA.fromBufferAttribute( uv2, a );\r\n\t\t\t\t_uvB.fromBufferAttribute( uv2, b );\r\n\t\t\t\t_uvC.fromBufferAttribute( uv2, c );\r\n\r\n\t\t\t\tintersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar face = new Face3( a, b, c );\r\n\t\t\tTriangle.getNormal( _vA, _vB, _vC, face.normal );\r\n\r\n\t\t\tintersection.face = face;\r\n\r\n\t\t}\r\n\r\n\t\treturn intersection;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author kile / http://kile.stravaganza.org/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _geometryId = 0; // Geometry uses even numbers as Id\r\n\tvar _m1$3 = new Matrix4();\r\n\tvar _obj$1 = new Object3D();\r\n\tvar _offset$1 = new Vector3();\r\n\r\n\tfunction Geometry() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _geometryId += 2 } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Geometry';\r\n\r\n\t\tthis.vertices = [];\r\n\t\tthis.colors = [];\r\n\t\tthis.faces = [];\r\n\t\tthis.faceVertexUvs = [[]];\r\n\r\n\t\tthis.morphTargets = [];\r\n\t\tthis.morphNormals = [];\r\n\r\n\t\tthis.skinWeights = [];\r\n\t\tthis.skinIndices = [];\r\n\r\n\t\tthis.lineDistances = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\t// update flags\r\n\r\n\t\tthis.elementsNeedUpdate = false;\r\n\t\tthis.verticesNeedUpdate = false;\r\n\t\tthis.uvsNeedUpdate = false;\r\n\t\tthis.normalsNeedUpdate = false;\r\n\t\tthis.colorsNeedUpdate = false;\r\n\t\tthis.lineDistancesNeedUpdate = false;\r\n\t\tthis.groupsNeedUpdate = false;\r\n\r\n\t}\r\n\r\n\tGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Geometry,\r\n\r\n\t\tisGeometry: true,\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\tfor ( var i = 0, il = this.vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = this.vertices[ i ];\r\n\t\t\t\tvertex.applyMatrix4( matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, il = this.faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ i ];\r\n\t\t\t\tface.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tface.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.verticesNeedUpdate = true;\r\n\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world x-axis\r\n\r\n\t\t\t_m1$3.makeRotationX( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world y-axis\r\n\r\n\t\t\t_m1$3.makeRotationY( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world z-axis\r\n\r\n\t\t\t_m1$3.makeRotationZ( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( x, y, z ) {\r\n\r\n\t\t\t// translate geometry\r\n\r\n\t\t\t_m1$3.makeTranslation( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( x, y, z ) {\r\n\r\n\t\t\t// scale geometry\r\n\r\n\t\t\t_m1$3.makeScale( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( vector ) {\r\n\r\n\t\t\t_obj$1.lookAt( vector );\r\n\r\n\t\t\t_obj$1.updateMatrix();\r\n\r\n\t\t\tthis.applyMatrix( _obj$1.matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar indices = geometry.index !== null ? geometry.index.array : undefined;\r\n\t\t\tvar attributes = geometry.attributes;\r\n\r\n\t\t\tif ( attributes.position === undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar positions = attributes.position.array;\r\n\t\t\tvar normals = attributes.normal !== undefined ? attributes.normal.array : undefined;\r\n\t\t\tvar colors = attributes.color !== undefined ? attributes.color.array : undefined;\r\n\t\t\tvar uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;\r\n\t\t\tvar uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;\r\n\r\n\t\t\tif ( uvs2 !== undefined ) { this.faceVertexUvs[ 1 ] = []; }\r\n\r\n\t\t\tfor ( var i = 0; i < positions.length; i += 3 ) {\r\n\r\n\t\t\t\tscope.vertices.push( new Vector3().fromArray( positions, i ) );\r\n\r\n\t\t\t\tif ( colors !== undefined ) {\r\n\r\n\t\t\t\t\tscope.colors.push( new Color().fromArray( colors, i ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction addFace( a, b, c, materialIndex ) {\r\n\r\n\t\t\t\tvar vertexColors = ( colors === undefined ) ? [] : [\r\n\t\t\t\t\tscope.colors[ a ].clone(),\r\n\t\t\t\t\tscope.colors[ b ].clone(),\r\n\t\t\t\t\tscope.colors[ c ].clone() ];\r\n\r\n\t\t\t\tvar vertexNormals = ( normals === undefined ) ? [] : [\r\n\t\t\t\t\tnew Vector3().fromArray( normals, a * 3 ),\r\n\t\t\t\t\tnew Vector3().fromArray( normals, b * 3 ),\r\n\t\t\t\t\tnew Vector3().fromArray( normals, c * 3 )\r\n\t\t\t\t];\r\n\r\n\t\t\t\tvar face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );\r\n\r\n\t\t\t\tscope.faces.push( face );\r\n\r\n\t\t\t\tif ( uvs !== undefined ) {\r\n\r\n\t\t\t\t\tscope.faceVertexUvs[ 0 ].push( [\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, a * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, b * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, c * 2 )\r\n\t\t\t\t\t] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uvs2 !== undefined ) {\r\n\r\n\t\t\t\t\tscope.faceVertexUvs[ 1 ].push( [\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, a * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, b * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, c * 2 )\r\n\t\t\t\t\t] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\tif ( groups.length > 0 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < groups.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar group = groups[ i ];\r\n\r\n\t\t\t\t\tvar start = group.start;\r\n\t\t\t\t\tvar count = group.count;\r\n\r\n\t\t\t\t\tfor ( var j = start, jl = start + count; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\tif ( indices !== undefined ) {\r\n\r\n\t\t\t\t\t\t\taddFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\taddFace( j, j + 1, j + 2, group.materialIndex );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( indices !== undefined ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\r\n\r\n\t\t\t\t\t\taddFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < positions.length / 3; i += 3 ) {\r\n\r\n\t\t\t\t\t\taddFace( i, i + 1, i + 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function () {\r\n\r\n\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\tthis.boundingBox.getCenter( _offset$1 ).negate();\r\n\r\n\t\t\tthis.translate( _offset$1.x, _offset$1.y, _offset$1.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\tvar center = this.boundingSphere.center;\r\n\t\t\tvar radius = this.boundingSphere.radius;\r\n\r\n\t\t\tvar s = radius === 0 ? 1 : 1.0 / radius;\r\n\r\n\t\t\tvar matrix = new Matrix4();\r\n\t\t\tmatrix.set(\r\n\t\t\t\ts, 0, 0, - s * center.x,\r\n\t\t\t\t0, s, 0, - s * center.y,\r\n\t\t\t\t0, 0, s, - s * center.z,\r\n\t\t\t\t0, 0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t\tthis.applyMatrix( matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFaceNormals: function () {\r\n\r\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\tfor ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ f ];\r\n\r\n\t\t\t\tvar vA = this.vertices[ face.a ];\r\n\t\t\t\tvar vB = this.vertices[ face.b ];\r\n\t\t\t\tvar vC = this.vertices[ face.c ];\r\n\r\n\t\t\t\tcb.subVectors( vC, vB );\r\n\t\t\t\tab.subVectors( vA, vB );\r\n\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\tcb.normalize();\r\n\r\n\t\t\t\tface.normal.copy( cb );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeVertexNormals: function ( areaWeighted ) {\r\n\r\n\t\t\tif ( areaWeighted === undefined ) { areaWeighted = true; }\r\n\r\n\t\t\tvar v, vl, f, fl, face, vertices;\r\n\r\n\t\t\tvertices = new Array( this.vertices.length );\r\n\r\n\t\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\r\n\r\n\t\t\t\tvertices[ v ] = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( areaWeighted ) {\r\n\r\n\t\t\t\t// vertex normals weighted by triangle areas\r\n\t\t\t\t// http://www.iquilezles.org/www/articles/normals/normals.htm\r\n\r\n\t\t\t\tvar vA, vB, vC;\r\n\t\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tvA = this.vertices[ face.a ];\r\n\t\t\t\t\tvB = this.vertices[ face.b ];\r\n\t\t\t\t\tvC = this.vertices[ face.c ];\r\n\r\n\t\t\t\t\tcb.subVectors( vC, vB );\r\n\t\t\t\t\tab.subVectors( vA, vB );\r\n\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\tvertices[ face.a ].add( cb );\r\n\t\t\t\t\tvertices[ face.b ].add( cb );\r\n\t\t\t\t\tvertices[ face.c ].add( cb );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tvertices[ face.a ].add( face.normal );\r\n\t\t\t\t\tvertices[ face.b ].add( face.normal );\r\n\t\t\t\t\tvertices[ face.c ].add( face.normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\r\n\r\n\t\t\t\tvertices[ v ].normalize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ].copy( vertices[ face.a ] );\r\n\t\t\t\t\tvertexNormals[ 1 ].copy( vertices[ face.b ] );\r\n\t\t\t\t\tvertexNormals[ 2 ].copy( vertices[ face.c ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ] = vertices[ face.a ].clone();\r\n\t\t\t\t\tvertexNormals[ 1 ] = vertices[ face.b ].clone();\r\n\t\t\t\t\tvertexNormals[ 2 ] = vertices[ face.c ].clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.faces.length > 0 ) {\r\n\r\n\t\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFlatVertexNormals: function () {\r\n\r\n\t\t\tvar f, fl, face;\r\n\r\n\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ].copy( face.normal );\r\n\t\t\t\t\tvertexNormals[ 1 ].copy( face.normal );\r\n\t\t\t\t\tvertexNormals[ 2 ].copy( face.normal );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ] = face.normal.clone();\r\n\t\t\t\t\tvertexNormals[ 1 ] = face.normal.clone();\r\n\t\t\t\t\tvertexNormals[ 2 ] = face.normal.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.faces.length > 0 ) {\r\n\r\n\t\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeMorphNormals: function () {\r\n\r\n\t\t\tvar i, il, f, fl, face;\r\n\r\n\t\t\t// save original normals\r\n\t\t\t// - create temp variables on first access\r\n\t\t\t// otherwise just copy (for faster repeated calls)\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tif ( ! face.__originalFaceNormal ) {\r\n\r\n\t\t\t\t\tface.__originalFaceNormal = face.normal.clone();\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tface.__originalFaceNormal.copy( face.normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ! face.__originalVertexNormals ) { face.__originalVertexNormals = []; }\r\n\r\n\t\t\t\tfor ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tif ( ! face.__originalVertexNormals[ i ] ) {\r\n\r\n\t\t\t\t\t\tface.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tface.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// use temp geometry to compute face and vertex normals for each morph\r\n\r\n\t\t\tvar tmpGeo = new Geometry();\r\n\t\t\ttmpGeo.faces = this.faces;\r\n\r\n\t\t\tfor ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// create on first access\r\n\r\n\t\t\t\tif ( ! this.morphNormals[ i ] ) {\r\n\r\n\t\t\t\t\tthis.morphNormals[ i ] = {};\r\n\t\t\t\t\tthis.morphNormals[ i ].faceNormals = [];\r\n\t\t\t\t\tthis.morphNormals[ i ].vertexNormals = [];\r\n\r\n\t\t\t\t\tvar dstNormalsFace = this.morphNormals[ i ].faceNormals;\r\n\t\t\t\t\tvar dstNormalsVertex = this.morphNormals[ i ].vertexNormals;\r\n\r\n\t\t\t\t\tvar faceNormal, vertexNormals;\r\n\r\n\t\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\t\tfaceNormal = new Vector3();\r\n\t\t\t\t\t\tvertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };\r\n\r\n\t\t\t\t\t\tdstNormalsFace.push( faceNormal );\r\n\t\t\t\t\t\tdstNormalsVertex.push( vertexNormals );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar morphNormals = this.morphNormals[ i ];\r\n\r\n\t\t\t\t// set vertices to morph target\r\n\r\n\t\t\t\ttmpGeo.vertices = this.morphTargets[ i ].vertices;\r\n\r\n\t\t\t\t// compute morph normals\r\n\r\n\t\t\t\ttmpGeo.computeFaceNormals();\r\n\t\t\t\ttmpGeo.computeVertexNormals();\r\n\r\n\t\t\t\t// store morph normals\r\n\r\n\t\t\t\tvar faceNormal, vertexNormals;\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tfaceNormal = morphNormals.faceNormals[ f ];\r\n\t\t\t\t\tvertexNormals = morphNormals.vertexNormals[ f ];\r\n\r\n\t\t\t\t\tfaceNormal.copy( face.normal );\r\n\r\n\t\t\t\t\tvertexNormals.a.copy( face.vertexNormals[ 0 ] );\r\n\t\t\t\t\tvertexNormals.b.copy( face.vertexNormals[ 1 ] );\r\n\t\t\t\t\tvertexNormals.c.copy( face.vertexNormals[ 2 ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// restore original normals\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tface.normal = face.__originalFaceNormal;\r\n\t\t\t\tface.vertexNormals = face.__originalVertexNormals;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingBox: function () {\r\n\r\n\t\t\tif ( this.boundingBox === null ) {\r\n\r\n\t\t\t\tthis.boundingBox = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.boundingBox.setFromPoints( this.vertices );\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingSphere: function () {\r\n\r\n\t\t\tif ( this.boundingSphere === null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = new Sphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.boundingSphere.setFromPoints( this.vertices );\r\n\r\n\t\t},\r\n\r\n\t\tmerge: function ( geometry, matrix, materialIndexOffset ) {\r\n\r\n\t\t\tif ( ! ( geometry && geometry.isGeometry ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar normalMatrix,\r\n\t\t\t\tvertexOffset = this.vertices.length,\r\n\t\t\t\tvertices1 = this.vertices,\r\n\t\t\t\tvertices2 = geometry.vertices,\r\n\t\t\t\tfaces1 = this.faces,\r\n\t\t\t\tfaces2 = geometry.faces,\r\n\t\t\t\tcolors1 = this.colors,\r\n\t\t\t\tcolors2 = geometry.colors;\r\n\r\n\t\t\tif ( materialIndexOffset === undefined ) { materialIndexOffset = 0; }\r\n\r\n\t\t\tif ( matrix !== undefined ) {\r\n\r\n\t\t\t\tnormalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// vertices\r\n\r\n\t\t\tfor ( var i = 0, il = vertices2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = vertices2[ i ];\r\n\r\n\t\t\t\tvar vertexCopy = vertex.clone();\r\n\r\n\t\t\t\tif ( matrix !== undefined ) { vertexCopy.applyMatrix4( matrix ); }\r\n\r\n\t\t\t\tvertices1.push( vertexCopy );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// colors\r\n\r\n\t\t\tfor ( var i = 0, il = colors2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tcolors1.push( colors2[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// faces\r\n\r\n\t\t\tfor ( i = 0, il = faces2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces2[ i ], faceCopy, normal, color,\r\n\t\t\t\t\tfaceVertexNormals = face.vertexNormals,\r\n\t\t\t\t\tfaceVertexColors = face.vertexColors;\r\n\r\n\t\t\t\tfaceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );\r\n\t\t\t\tfaceCopy.normal.copy( face.normal );\r\n\r\n\t\t\t\tif ( normalMatrix !== undefined ) {\r\n\r\n\t\t\t\t\tfaceCopy.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tnormal = faceVertexNormals[ j ].clone();\r\n\r\n\t\t\t\t\tif ( normalMatrix !== undefined ) {\r\n\r\n\t\t\t\t\t\tnormal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfaceCopy.vertexNormals.push( normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfaceCopy.color.copy( face.color );\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tcolor = faceVertexColors[ j ];\r\n\t\t\t\t\tfaceCopy.vertexColors.push( color.clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfaceCopy.materialIndex = face.materialIndex + materialIndexOffset;\r\n\r\n\t\t\t\tfaces1.push( faceCopy );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uvs\r\n\r\n\t\t\tfor ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar faceVertexUvs2 = geometry.faceVertexUvs[ i ];\r\n\r\n\t\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) { this.faceVertexUvs[ i ] = []; }\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar uvs2 = faceVertexUvs2[ j ], uvsCopy = [];\r\n\r\n\t\t\t\t\tfor ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\tuvsCopy.push( uvs2[ k ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tmergeMesh: function ( mesh ) {\r\n\r\n\t\t\tif ( ! ( mesh && mesh.isMesh ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( mesh.matrixAutoUpdate ) { mesh.updateMatrix(); }\r\n\r\n\t\t\tthis.merge( mesh.geometry, mesh.matrix );\r\n\r\n\t\t},\r\n\r\n\t\t/*\r\n\t\t * Checks for duplicate vertices with hashmap.\r\n\t\t * Duplicated vertices are removed\r\n\t\t * and faces' vertices are updated.\r\n\t\t */\r\n\r\n\t\tmergeVertices: function () {\r\n\r\n\t\t\tvar verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)\r\n\t\t\tvar unique = [], changes = [];\r\n\r\n\t\t\tvar v, key;\r\n\t\t\tvar precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001\r\n\t\t\tvar precision = Math.pow( 10, precisionPoints );\r\n\t\t\tvar i, il, face;\r\n\t\t\tvar indices, j, jl;\r\n\r\n\t\t\tfor ( i = 0, il = this.vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tv = this.vertices[ i ];\r\n\t\t\t\tkey = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );\r\n\r\n\t\t\t\tif ( verticesMap[ key ] === undefined ) {\r\n\r\n\t\t\t\t\tverticesMap[ key ] = i;\r\n\t\t\t\t\tunique.push( this.vertices[ i ] );\r\n\t\t\t\t\tchanges[ i ] = unique.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);\r\n\t\t\t\t\tchanges[ i ] = changes[ verticesMap[ key ] ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// if faces are completely degenerate after merging vertices, we\r\n\t\t\t// have to remove them from the geometry.\r\n\t\t\tvar faceIndicesToRemove = [];\r\n\r\n\t\t\tfor ( i = 0, il = this.faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ i ];\r\n\r\n\t\t\t\tface.a = changes[ face.a ];\r\n\t\t\t\tface.b = changes[ face.b ];\r\n\t\t\t\tface.c = changes[ face.c ];\r\n\r\n\t\t\t\tindices = [ face.a, face.b, face.c ];\r\n\r\n\t\t\t\t// if any duplicate vertices are found in a Face3\r\n\t\t\t\t// we have to remove the face as nothing can be saved\r\n\t\t\t\tfor ( var n = 0; n < 3; n ++ ) {\r\n\r\n\t\t\t\t\tif ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {\r\n\r\n\t\t\t\t\t\tfaceIndicesToRemove.push( i );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {\r\n\r\n\t\t\t\tvar idx = faceIndicesToRemove[ i ];\r\n\r\n\t\t\t\tthis.faces.splice( idx, 1 );\r\n\r\n\t\t\t\tfor ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ j ].splice( idx, 1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Use unique set of vertices\r\n\r\n\t\t\tvar diff = this.vertices.length - unique.length;\r\n\t\t\tthis.vertices = unique;\r\n\t\t\treturn diff;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.vertices = [];\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tthis.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsortFacesByMaterialIndex: function () {\r\n\r\n\t\t\tvar faces = this.faces;\r\n\t\t\tvar length = faces.length;\r\n\r\n\t\t\t// tag faces\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tfaces[ i ]._id = i;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// sort faces\r\n\r\n\t\t\tfunction materialIndexSort( a, b ) {\r\n\r\n\t\t\t\treturn a.materialIndex - b.materialIndex;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfaces.sort( materialIndexSort );\r\n\r\n\t\t\t// sort uvs\r\n\r\n\t\t\tvar uvs1 = this.faceVertexUvs[ 0 ];\r\n\t\t\tvar uvs2 = this.faceVertexUvs[ 1 ];\r\n\r\n\t\t\tvar newUvs1, newUvs2;\r\n\r\n\t\t\tif ( uvs1 && uvs1.length === length ) { newUvs1 = []; }\r\n\t\t\tif ( uvs2 && uvs2.length === length ) { newUvs2 = []; }\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar id = faces[ i ]._id;\r\n\r\n\t\t\t\tif ( newUvs1 ) { newUvs1.push( uvs1[ id ] ); }\r\n\t\t\t\tif ( newUvs2 ) { newUvs2.push( uvs2[ id ] ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( newUvs1 ) { this.faceVertexUvs[ 0 ] = newUvs1; }\r\n\t\t\tif ( newUvs2 ) { this.faceVertexUvs[ 1 ] = newUvs2; }\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Geometry',\r\n\t\t\t\t\tgenerator: 'Geometry.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard Geometry serialization\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\r\n\t\t\tif ( this.parameters !== undefined ) {\r\n\r\n\t\t\t\tvar parameters = this.parameters;\r\n\r\n\t\t\t\tfor ( var key in parameters ) {\r\n\r\n\t\t\t\t\tif ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn data;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vertices = [];\r\n\r\n\t\t\tfor ( var i = 0; i < this.vertices.length; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = this.vertices[ i ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar faces = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar normalsHash = {};\r\n\t\t\tvar colors = [];\r\n\t\t\tvar colorsHash = {};\r\n\t\t\tvar uvs = [];\r\n\t\t\tvar uvsHash = {};\r\n\r\n\t\t\tfor ( var i = 0; i < this.faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ i ];\r\n\r\n\t\t\t\tvar hasMaterial = true;\r\n\t\t\t\tvar hasFaceUv = false; // deprecated\r\n\t\t\t\tvar hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;\r\n\t\t\t\tvar hasFaceNormal = face.normal.length() > 0;\r\n\t\t\t\tvar hasFaceVertexNormal = face.vertexNormals.length > 0;\r\n\t\t\t\tvar hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;\r\n\t\t\t\tvar hasFaceVertexColor = face.vertexColors.length > 0;\r\n\r\n\t\t\t\tvar faceType = 0;\r\n\r\n\t\t\t\tfaceType = setBit( faceType, 0, 0 ); // isQuad\r\n\t\t\t\tfaceType = setBit( faceType, 1, hasMaterial );\r\n\t\t\t\tfaceType = setBit( faceType, 2, hasFaceUv );\r\n\t\t\t\tfaceType = setBit( faceType, 3, hasFaceVertexUv );\r\n\t\t\t\tfaceType = setBit( faceType, 4, hasFaceNormal );\r\n\t\t\t\tfaceType = setBit( faceType, 5, hasFaceVertexNormal );\r\n\t\t\t\tfaceType = setBit( faceType, 6, hasFaceColor );\r\n\t\t\t\tfaceType = setBit( faceType, 7, hasFaceVertexColor );\r\n\r\n\t\t\t\tfaces.push( faceType );\r\n\t\t\t\tfaces.push( face.a, face.b, face.c );\r\n\t\t\t\tfaces.push( face.materialIndex );\r\n\r\n\t\t\t\tif ( hasFaceVertexUv ) {\r\n\r\n\t\t\t\t\tvar faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 0 ] ),\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 1 ] ),\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceNormal ) {\r\n\r\n\t\t\t\t\tfaces.push( getNormalIndex( face.normal ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexNormal ) {\r\n\r\n\t\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 0 ] ),\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 1 ] ),\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceColor ) {\r\n\r\n\t\t\t\t\tfaces.push( getColorIndex( face.color ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexColor ) {\r\n\r\n\t\t\t\t\tvar vertexColors = face.vertexColors;\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 0 ] ),\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 1 ] ),\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction setBit( value, position, enabled ) {\r\n\r\n\t\t\t\treturn enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getNormalIndex( normal ) {\r\n\r\n\t\t\t\tvar hash = normal.x.toString() + normal.y.toString() + normal.z.toString();\r\n\r\n\t\t\t\tif ( normalsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn normalsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnormalsHash[ hash ] = normals.length / 3;\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\treturn normalsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getColorIndex( color ) {\r\n\r\n\t\t\t\tvar hash = color.r.toString() + color.g.toString() + color.b.toString();\r\n\r\n\t\t\t\tif ( colorsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn colorsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcolorsHash[ hash ] = colors.length;\r\n\t\t\t\tcolors.push( color.getHex() );\r\n\r\n\t\t\t\treturn colorsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getUvIndex( uv ) {\r\n\r\n\t\t\t\tvar hash = uv.x.toString() + uv.y.toString();\r\n\r\n\t\t\t\tif ( uvsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn uvsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuvsHash[ hash ] = uvs.length / 2;\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\treturn uvsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdata.data = {};\r\n\r\n\t\t\tdata.data.vertices = vertices;\r\n\t\t\tdata.data.normals = normals;\r\n\t\t\tif ( colors.length > 0 ) { data.data.colors = colors; }\r\n\t\t\tif ( uvs.length > 0 ) { data.data.uvs = [ uvs ]; } // temporal backward compatibility\r\n\t\t\tdata.data.faces = faces;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\t/*\r\n\t\t\t // Handle primitives\r\n\r\n\t\t\t var parameters = this.parameters;\r\n\r\n\t\t\t if ( parameters !== undefined ) {\r\n\r\n\t\t\t var values = [];\r\n\r\n\t\t\t for ( var key in parameters ) {\r\n\r\n\t\t\t values.push( parameters[ key ] );\r\n\r\n\t\t\t }\r\n\r\n\t\t\t var geometry = Object.create( this.constructor.prototype );\r\n\t\t\t this.constructor.apply( geometry, values );\r\n\t\t\t return geometry;\r\n\r\n\t\t\t }\r\n\r\n\t\t\t return new this.constructor().copy( this );\r\n\t\t\t */\r\n\r\n\t\t\treturn new Geometry().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tvar i, il, j, jl, k, kl;\r\n\r\n\t\t\t// reset\r\n\r\n\t\t\tthis.vertices = [];\r\n\t\t\tthis.colors = [];\r\n\t\t\tthis.faces = [];\r\n\t\t\tthis.faceVertexUvs = [[]];\r\n\t\t\tthis.morphTargets = [];\r\n\t\t\tthis.morphNormals = [];\r\n\t\t\tthis.skinWeights = [];\r\n\t\t\tthis.skinIndices = [];\r\n\t\t\tthis.lineDistances = [];\r\n\t\t\tthis.boundingBox = null;\r\n\t\t\tthis.boundingSphere = null;\r\n\r\n\t\t\t// name\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\t// vertices\r\n\r\n\t\t\tvar vertices = source.vertices;\r\n\r\n\t\t\tfor ( i = 0, il = vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertices.push( vertices[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// colors\r\n\r\n\t\t\tvar colors = source.colors;\r\n\r\n\t\t\tfor ( i = 0, il = colors.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.colors.push( colors[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// faces\r\n\r\n\t\t\tvar faces = source.faces;\r\n\r\n\t\t\tfor ( i = 0, il = faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.faces.push( faces[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// face vertex uvs\r\n\r\n\t\t\tfor ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar faceVertexUvs = source.faceVertexUvs[ i ];\r\n\r\n\t\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) {\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ] = [];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar uvs = faceVertexUvs[ j ], uvsCopy = [];\r\n\r\n\t\t\t\t\tfor ( k = 0, kl = uvs.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\tvar uv = uvs[ k ];\r\n\r\n\t\t\t\t\t\tuvsCopy.push( uv.clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph targets\r\n\r\n\t\t\tvar morphTargets = source.morphTargets;\r\n\r\n\t\t\tfor ( i = 0, il = morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphTarget = {};\r\n\t\t\t\tmorphTarget.name = morphTargets[ i ].name;\r\n\r\n\t\t\t\t// vertices\r\n\r\n\t\t\t\tif ( morphTargets[ i ].vertices !== undefined ) {\r\n\r\n\t\t\t\t\tmorphTarget.vertices = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// normals\r\n\r\n\t\t\t\tif ( morphTargets[ i ].normals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphTarget.normals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.push( morphTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph normals\r\n\r\n\t\t\tvar morphNormals = source.morphNormals;\r\n\r\n\t\t\tfor ( i = 0, il = morphNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphNormal = {};\r\n\r\n\t\t\t\t// vertex normals\r\n\r\n\t\t\t\tif ( morphNormals[ i ].vertexNormals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphNormal.vertexNormals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tvar srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];\r\n\t\t\t\t\t\tvar destVertexNormal = {};\r\n\r\n\t\t\t\t\t\tdestVertexNormal.a = srcVertexNormal.a.clone();\r\n\t\t\t\t\t\tdestVertexNormal.b = srcVertexNormal.b.clone();\r\n\t\t\t\t\t\tdestVertexNormal.c = srcVertexNormal.c.clone();\r\n\r\n\t\t\t\t\t\tmorphNormal.vertexNormals.push( destVertexNormal );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// face normals\r\n\r\n\t\t\t\tif ( morphNormals[ i ].faceNormals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphNormal.faceNormals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphNormals.push( morphNormal );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skin weights\r\n\r\n\t\t\tvar skinWeights = source.skinWeights;\r\n\r\n\t\t\tfor ( i = 0, il = skinWeights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.skinWeights.push( skinWeights[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skin indices\r\n\r\n\t\t\tvar skinIndices = source.skinIndices;\r\n\r\n\t\t\tfor ( i = 0, il = skinIndices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.skinIndices.push( skinIndices[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// line distances\r\n\r\n\t\t\tvar lineDistances = source.lineDistances;\r\n\r\n\t\t\tfor ( i = 0, il = lineDistances.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.lineDistances.push( lineDistances[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding box\r\n\r\n\t\t\tvar boundingBox = source.boundingBox;\r\n\r\n\t\t\tif ( boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding sphere\r\n\r\n\t\t\tvar boundingSphere = source.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update flags\r\n\r\n\t\t\tthis.elementsNeedUpdate = source.elementsNeedUpdate;\r\n\t\t\tthis.verticesNeedUpdate = source.verticesNeedUpdate;\r\n\t\t\tthis.uvsNeedUpdate = source.uvsNeedUpdate;\r\n\t\t\tthis.normalsNeedUpdate = source.normalsNeedUpdate;\r\n\t\t\tthis.colorsNeedUpdate = source.colorsNeedUpdate;\r\n\t\t\tthis.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;\r\n\t\t\tthis.groupsNeedUpdate = source.groupsNeedUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// BoxGeometry\r\n\r\n\tvar BoxGeometry = /*@__PURE__*/(function (Geometry) {\n\t\tfunction BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {\r\n\r\n\t\t\tGeometry.call(this);\r\n\r\n\t\t\tthis.type = 'BoxGeometry';\r\n\r\n\t\t\tthis.parameters = {\r\n\t\t\t\twidth: width,\r\n\t\t\t\theight: height,\r\n\t\t\t\tdepth: depth,\r\n\t\t\t\twidthSegments: widthSegments,\r\n\t\t\t\theightSegments: heightSegments,\r\n\t\t\t\tdepthSegments: depthSegments\r\n\t\t\t};\r\n\r\n\t\t\tthis.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );\r\n\t\t\tthis.mergeVertices();\r\n\r\n\t\t}\n\n\t\tif ( Geometry ) BoxGeometry.__proto__ = Geometry;\n\t\tBoxGeometry.prototype = Object.create( Geometry && Geometry.prototype );\n\t\tBoxGeometry.prototype.constructor = BoxGeometry;\n\n\t\treturn BoxGeometry;\n\t}(Geometry));\r\n\r\n\t// BoxBufferGeometry\r\n\r\n\tvar BoxBufferGeometry = /*@__PURE__*/(function (BufferGeometry) {\n\t\tfunction BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {\r\n\r\n\t\t\tBufferGeometry.call(this);\r\n\r\n\t\t\tthis.type = 'BoxBufferGeometry';\r\n\r\n\t\t\tthis.parameters = {\r\n\t\t\t\twidth: width,\r\n\t\t\t\theight: height,\r\n\t\t\t\tdepth: depth,\r\n\t\t\t\twidthSegments: widthSegments,\r\n\t\t\t\theightSegments: heightSegments,\r\n\t\t\t\tdepthSegments: depthSegments\r\n\t\t\t};\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\twidth = width || 1;\r\n\t\t\theight = height || 1;\r\n\t\t\tdepth = depth || 1;\r\n\r\n\t\t\t// segments\r\n\r\n\t\t\twidthSegments = Math.floor( widthSegments ) || 1;\r\n\t\t\theightSegments = Math.floor( heightSegments ) || 1;\r\n\t\t\tdepthSegments = Math.floor( depthSegments ) || 1;\r\n\r\n\t\t\t// buffers\r\n\r\n\t\t\tvar indices = [];\r\n\t\t\tvar vertices = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar uvs = [];\r\n\r\n\t\t\t// helper variables\r\n\r\n\t\t\tvar numberOfVertices = 0;\r\n\t\t\tvar groupStart = 0;\r\n\r\n\t\t\t// build each side of the box geometry\r\n\r\n\t\t\tbuildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px\r\n\t\t\tbuildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx\r\n\t\t\tbuildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py\r\n\t\t\tbuildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny\r\n\t\t\tbuildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz\r\n\t\t\tbuildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz\r\n\r\n\t\t\t// build geometry\r\n\r\n\t\t\tthis.setIndex( indices );\r\n\t\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t\tfunction buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {\r\n\r\n\t\t\t\tvar segmentWidth = width / gridX;\r\n\t\t\t\tvar segmentHeight = height / gridY;\r\n\r\n\t\t\t\tvar widthHalf = width / 2;\r\n\t\t\t\tvar heightHalf = height / 2;\r\n\t\t\t\tvar depthHalf = depth / 2;\r\n\r\n\t\t\t\tvar gridX1 = gridX + 1;\r\n\t\t\t\tvar gridY1 = gridY + 1;\r\n\r\n\t\t\t\tvar vertexCounter = 0;\r\n\t\t\t\tvar groupCount = 0;\r\n\r\n\t\t\t\tvar ix, iy;\r\n\r\n\t\t\t\tvar vector = new Vector3();\r\n\r\n\t\t\t\t// generate vertices, normals and uvs\r\n\r\n\t\t\t\tfor ( iy = 0; iy < gridY1; iy ++ ) {\r\n\r\n\t\t\t\t\tvar y = iy * segmentHeight - heightHalf;\r\n\r\n\t\t\t\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\r\n\r\n\t\t\t\t\t\tvar x = ix * segmentWidth - widthHalf;\r\n\r\n\t\t\t\t\t\t// set values to correct vector component\r\n\r\n\t\t\t\t\t\tvector[ u ] = x * udir;\r\n\t\t\t\t\t\tvector[ v ] = y * vdir;\r\n\t\t\t\t\t\tvector[ w ] = depthHalf;\r\n\r\n\t\t\t\t\t\t// now apply vector to vertex buffer\r\n\r\n\t\t\t\t\t\tvertices.push( vector.x, vector.y, vector.z );\r\n\r\n\t\t\t\t\t\t// set values to correct vector component\r\n\r\n\t\t\t\t\t\tvector[ u ] = 0;\r\n\t\t\t\t\t\tvector[ v ] = 0;\r\n\t\t\t\t\t\tvector[ w ] = depth > 0 ? 1 : - 1;\r\n\r\n\t\t\t\t\t\t// now apply vector to normal buffer\r\n\r\n\t\t\t\t\t\tnormals.push( vector.x, vector.y, vector.z );\r\n\r\n\t\t\t\t\t\t// uvs\r\n\r\n\t\t\t\t\t\tuvs.push( ix / gridX );\r\n\t\t\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\r\n\r\n\t\t\t\t\t\t// counters\r\n\r\n\t\t\t\t\t\tvertexCounter += 1;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\t// 1. you need three indices to draw a single face\r\n\t\t\t\t// 2. a single segment consists of two faces\r\n\t\t\t\t// 3. so we need to generate six (2*3) indices per segment\r\n\r\n\t\t\t\tfor ( iy = 0; iy < gridY; iy ++ ) {\r\n\r\n\t\t\t\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\r\n\r\n\t\t\t\t\t\tvar a = numberOfVertices + ix + gridX1 * iy;\r\n\t\t\t\t\t\tvar b = numberOfVertices + ix + gridX1 * ( iy + 1 );\r\n\t\t\t\t\t\tvar c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );\r\n\t\t\t\t\t\tvar d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;\r\n\r\n\t\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t\t\t// increase counter\r\n\r\n\t\t\t\t\t\tgroupCount += 6;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\t\tscope.addGroup( groupStart, groupCount, materialIndex );\r\n\r\n\t\t\t\t// calculate new start value for groups\r\n\r\n\t\t\t\tgroupStart += groupCount;\r\n\r\n\t\t\t\t// update total number of vertices\r\n\r\n\t\t\t\tnumberOfVertices += vertexCounter;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\n\n\t\tif ( BufferGeometry ) BoxBufferGeometry.__proto__ = BufferGeometry;\n\t\tBoxBufferGeometry.prototype = Object.create( BufferGeometry && BufferGeometry.prototype );\n\t\tBoxBufferGeometry.prototype.constructor = BoxBufferGeometry;\n\n\t\treturn BoxBufferGeometry;\n\t}(BufferGeometry));\n\n\t/**\r\n\t * Uniform Utilities\r\n\t */\r\n\r\n\tfunction cloneUniforms( src ) {\r\n\r\n\t\tvar dst = {};\r\n\r\n\t\tfor ( var u in src ) {\r\n\r\n\t\t\tdst[ u ] = {};\r\n\r\n\t\t\tfor ( var p in src[ u ] ) {\r\n\r\n\t\t\t\tvar property = src[ u ][ p ];\r\n\r\n\t\t\t\tif ( property && ( property.isColor ||\r\n\t\t\t\t\tproperty.isMatrix3 || property.isMatrix4 ||\r\n\t\t\t\t\tproperty.isVector2 || property.isVector3 || property.isVector4 ||\r\n\t\t\t\t\tproperty.isTexture ) ) {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property.clone();\r\n\r\n\t\t\t\t} else if ( Array.isArray( property ) ) {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property.slice();\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn dst;\r\n\r\n\t}\r\n\r\n\tfunction mergeUniforms( uniforms ) {\r\n\r\n\t\tvar merged = {};\r\n\r\n\t\tfor ( var u = 0; u < uniforms.length; u ++ ) {\r\n\r\n\t\t\tvar tmp = cloneUniforms( uniforms[ u ] );\r\n\r\n\t\t\tfor ( var p in tmp ) {\r\n\r\n\t\t\t\tmerged[ p ] = tmp[ p ];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn merged;\r\n\r\n\t}\r\n\r\n\t// Legacy\r\n\r\n\tvar UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };\n\n\tvar default_vertex = \"void main() {\\n\\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\n}\";\n\n\tvar default_fragment = \"void main() {\\n\\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\\n}\";\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * defines: { \"label\" : \"value\" },\r\n\t * uniforms: { \"parameter1\": { value: 1.0 }, \"parameter2\": { value2: 2 } },\r\n\t *\r\n\t * fragmentShader: ,\r\n\t * vertexShader: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * lights: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction ShaderMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'ShaderMaterial';\r\n\r\n\t\tthis.defines = {};\r\n\t\tthis.uniforms = {};\r\n\r\n\t\tthis.vertexShader = default_vertex;\r\n\t\tthis.fragmentShader = default_fragment;\r\n\r\n\t\tthis.linewidth = 1;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false; // set to use scene fog\r\n\t\tthis.lights = false; // set to use scene lights\r\n\t\tthis.clipping = false; // set to use user-defined clipping planes\r\n\r\n\t\tthis.skinning = false; // set to use skinning attribute streams\r\n\t\tthis.morphTargets = false; // set to use morph targets\r\n\t\tthis.morphNormals = false; // set to use morph normals\r\n\r\n\t\tthis.extensions = {\r\n\t\t\tderivatives: false, // set to use derivatives\r\n\t\t\tfragDepth: false, // set to use fragment depth values\r\n\t\t\tdrawBuffers: false, // set to use draw buffers\r\n\t\t\tshaderTextureLOD: false // set to use shader texture LOD\r\n\t\t};\r\n\r\n\t\t// When rendered geometry doesn't include these attributes but the material does,\r\n\t\t// use these default values in WebGL. This avoids errors when buffer data is missing.\r\n\t\tthis.defaultAttributeValues = {\r\n\t\t\t'color': [ 1, 1, 1 ],\r\n\t\t\t'uv': [ 0, 0 ],\r\n\t\t\t'uv2': [ 0, 0 ]\r\n\t\t};\r\n\r\n\t\tthis.index0AttributeName = undefined;\r\n\t\tthis.uniformsNeedUpdate = false;\r\n\r\n\t\tif ( parameters !== undefined ) {\r\n\r\n\t\t\tif ( parameters.attributes !== undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setValues( parameters );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tShaderMaterial.prototype = Object.create( Material.prototype );\r\n\tShaderMaterial.prototype.constructor = ShaderMaterial;\r\n\r\n\tShaderMaterial.prototype.isShaderMaterial = true;\r\n\r\n\tShaderMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.fragmentShader = source.fragmentShader;\r\n\t\tthis.vertexShader = source.vertexShader;\r\n\r\n\t\tthis.uniforms = cloneUniforms( source.uniforms );\r\n\r\n\t\tthis.defines = Object.assign( {}, source.defines );\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\tthis.lights = source.lights;\r\n\t\tthis.clipping = source.clipping;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\tthis.extensions = source.extensions;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tShaderMaterial.prototype.toJSON = function ( meta ) {\r\n\r\n\t\tvar data = Material.prototype.toJSON.call( this, meta );\r\n\r\n\t\tdata.uniforms = {};\r\n\r\n\t\tfor ( var name in this.uniforms ) {\r\n\r\n\t\t\tvar uniform = this.uniforms[ name ];\r\n\t\t\tvar value = uniform.value;\r\n\r\n\t\t\tif ( value && value.isTexture ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 't',\r\n\t\t\t\t\tvalue: value.toJSON( meta ).uuid\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isColor ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'c',\r\n\t\t\t\t\tvalue: value.getHex()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector2 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v2',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector3 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v3',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector4 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v4',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isMatrix3 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'm3',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isMatrix4 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'm4',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\tvalue: value\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( Object.keys( this.defines ).length > 0 ) { data.defines = this.defines; }\r\n\r\n\t\tdata.vertexShader = this.vertexShader;\r\n\t\tdata.fragmentShader = this.fragmentShader;\r\n\r\n\t\tvar extensions = {};\r\n\r\n\t\tfor ( var key in this.extensions ) {\r\n\r\n\t\t\tif ( this.extensions[ key ] === true ) { extensions[ key ] = true; }\r\n\r\n\t\t}\r\n\r\n\t\tif ( Object.keys( extensions ).length > 0 ) { data.extensions = extensions; }\r\n\r\n\t\treturn data;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t*/\r\n\r\n\tfunction Camera() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Camera';\r\n\r\n\t\tthis.matrixWorldInverse = new Matrix4();\r\n\r\n\t\tthis.projectionMatrix = new Matrix4();\r\n\t\tthis.projectionMatrixInverse = new Matrix4();\r\n\r\n\t}\r\n\r\n\tCamera.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Camera,\r\n\r\n\t\tisCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.matrixWorldInverse.copy( source.matrixWorldInverse );\r\n\r\n\t\t\tthis.projectionMatrix.copy( source.projectionMatrix );\r\n\t\t\tthis.projectionMatrixInverse.copy( source.projectionMatrixInverse );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldDirection: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Camera: .getWorldDirection() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tvar e = this.matrixWorld.elements;\r\n\r\n\t\t\treturn target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author greggman / http://games.greggman.com/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction PerspectiveCamera( fov, aspect, near, far ) {\r\n\r\n\t\tCamera.call( this );\r\n\r\n\t\tthis.type = 'PerspectiveCamera';\r\n\r\n\t\tthis.fov = fov !== undefined ? fov : 50;\r\n\t\tthis.zoom = 1;\r\n\r\n\t\tthis.near = near !== undefined ? near : 0.1;\r\n\t\tthis.far = far !== undefined ? far : 2000;\r\n\t\tthis.focus = 10;\r\n\r\n\t\tthis.aspect = aspect !== undefined ? aspect : 1;\r\n\t\tthis.view = null;\r\n\r\n\t\tthis.filmGauge = 35;\t// width of the film (default in millimeters)\r\n\t\tthis.filmOffset = 0;\t// horizontal film offset (same unit as gauge)\r\n\r\n\t\tthis.updateProjectionMatrix();\r\n\r\n\t}\r\n\r\n\tPerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\r\n\r\n\t\tconstructor: PerspectiveCamera,\r\n\r\n\t\tisPerspectiveCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tCamera.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.fov = source.fov;\r\n\t\t\tthis.zoom = source.zoom;\r\n\r\n\t\t\tthis.near = source.near;\r\n\t\t\tthis.far = source.far;\r\n\t\t\tthis.focus = source.focus;\r\n\r\n\t\t\tthis.aspect = source.aspect;\r\n\t\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\r\n\r\n\t\t\tthis.filmGauge = source.filmGauge;\r\n\t\t\tthis.filmOffset = source.filmOffset;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Sets the FOV by focal length in respect to the current .filmGauge.\r\n\t\t *\r\n\t\t * The default film gauge is 35, so that the focal length can be specified for\r\n\t\t * a 35mm (full frame) camera.\r\n\t\t *\r\n\t\t * Values for focal length and film gauge must have the same unit.\r\n\t\t */\r\n\t\tsetFocalLength: function ( focalLength ) {\r\n\r\n\t\t\t// see http://www.bobatkins.com/photography/technical/field_of_view.html\r\n\t\t\tvar vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;\r\n\r\n\t\t\tthis.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Calculates the focal length from the current .fov and .filmGauge.\r\n\t\t */\r\n\t\tgetFocalLength: function () {\r\n\r\n\t\t\tvar vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );\r\n\r\n\t\t\treturn 0.5 * this.getFilmHeight() / vExtentSlope;\r\n\r\n\t\t},\r\n\r\n\t\tgetEffectiveFOV: function () {\r\n\r\n\t\t\treturn _Math.RAD2DEG * 2 * Math.atan(\r\n\t\t\t\tMath.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );\r\n\r\n\t\t},\r\n\r\n\t\tgetFilmWidth: function () {\r\n\r\n\t\t\t// film not completely covered in portrait format (aspect < 1)\r\n\t\t\treturn this.filmGauge * Math.min( this.aspect, 1 );\r\n\r\n\t\t},\r\n\r\n\t\tgetFilmHeight: function () {\r\n\r\n\t\t\t// film not completely covered in landscape format (aspect > 1)\r\n\t\t\treturn this.filmGauge / Math.max( this.aspect, 1 );\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Sets an offset in a larger frustum. This is useful for multi-window or\r\n\t\t * multi-monitor/multi-machine setups.\r\n\t\t *\r\n\t\t * For example, if you have 3x2 monitors and each monitor is 1920x1080 and\r\n\t\t * the monitors are in grid like this\r\n\t\t *\r\n\t\t * +---+---+---+\r\n\t\t * | A | B | C |\r\n\t\t * +---+---+---+\r\n\t\t * | D | E | F |\r\n\t\t * +---+---+---+\r\n\t\t *\r\n\t\t * then for each monitor you would call it like this\r\n\t\t *\r\n\t\t * var w = 1920;\r\n\t\t * var h = 1080;\r\n\t\t * var fullWidth = w * 3;\r\n\t\t * var fullHeight = h * 2;\r\n\t\t *\r\n\t\t * --A--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );\r\n\t\t * --B--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );\r\n\t\t * --C--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );\r\n\t\t * --D--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );\r\n\t\t * --E--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );\r\n\t\t * --F--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );\r\n\t\t *\r\n\t\t * Note there is no reason monitors have to be the same size or in a grid.\r\n\t\t */\r\n\t\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\r\n\r\n\t\t\tthis.aspect = fullWidth / fullHeight;\r\n\r\n\t\t\tif ( this.view === null ) {\r\n\r\n\t\t\t\tthis.view = {\r\n\t\t\t\t\tenabled: true,\r\n\t\t\t\t\tfullWidth: 1,\r\n\t\t\t\t\tfullHeight: 1,\r\n\t\t\t\t\toffsetX: 0,\r\n\t\t\t\t\toffsetY: 0,\r\n\t\t\t\t\twidth: 1,\r\n\t\t\t\t\theight: 1\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.view.enabled = true;\r\n\t\t\tthis.view.fullWidth = fullWidth;\r\n\t\t\tthis.view.fullHeight = fullHeight;\r\n\t\t\tthis.view.offsetX = x;\r\n\t\t\tthis.view.offsetY = y;\r\n\t\t\tthis.view.width = width;\r\n\t\t\tthis.view.height = height;\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tclearViewOffset: function () {\r\n\r\n\t\t\tif ( this.view !== null ) {\r\n\r\n\t\t\t\tthis.view.enabled = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tupdateProjectionMatrix: function () {\r\n\r\n\t\t\tvar near = this.near,\r\n\t\t\t\ttop = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,\r\n\t\t\t\theight = 2 * top,\r\n\t\t\t\twidth = this.aspect * height,\r\n\t\t\t\tleft = - 0.5 * width,\r\n\t\t\t\tview = this.view;\r\n\r\n\t\t\tif ( this.view !== null && this.view.enabled ) {\r\n\r\n\t\t\t\tvar fullWidth = view.fullWidth,\r\n\t\t\t\t\tfullHeight = view.fullHeight;\r\n\r\n\t\t\t\tleft += view.offsetX * width / fullWidth;\r\n\t\t\t\ttop -= view.offsetY * height / fullHeight;\r\n\t\t\t\twidth *= view.width / fullWidth;\r\n\t\t\t\theight *= view.height / fullHeight;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar skew = this.filmOffset;\r\n\t\t\tif ( skew !== 0 ) { left += near * skew / this.getFilmWidth(); }\r\n\r\n\t\t\tthis.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );\r\n\r\n\t\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.fov = this.fov;\r\n\t\t\tdata.object.zoom = this.zoom;\r\n\r\n\t\t\tdata.object.near = this.near;\r\n\t\t\tdata.object.far = this.far;\r\n\t\t\tdata.object.focus = this.focus;\r\n\r\n\t\t\tdata.object.aspect = this.aspect;\r\n\r\n\t\t\tif ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); }\r\n\r\n\t\t\tdata.object.filmGauge = this.filmGauge;\r\n\t\t\tdata.object.filmOffset = this.filmOffset;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * Camera for rendering cube maps\r\n\t *\t- renders scene into axis-aligned cube\r\n\t *\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar fov = 90, aspect = 1;\r\n\r\n\tfunction CubeCamera( near, far, cubeResolution, options ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'CubeCamera';\r\n\r\n\t\tvar cameraPX = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPX.up.set( 0, - 1, 0 );\r\n\t\tcameraPX.lookAt( new Vector3( 1, 0, 0 ) );\r\n\t\tthis.add( cameraPX );\r\n\r\n\t\tvar cameraNX = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNX.up.set( 0, - 1, 0 );\r\n\t\tcameraNX.lookAt( new Vector3( - 1, 0, 0 ) );\r\n\t\tthis.add( cameraNX );\r\n\r\n\t\tvar cameraPY = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPY.up.set( 0, 0, 1 );\r\n\t\tcameraPY.lookAt( new Vector3( 0, 1, 0 ) );\r\n\t\tthis.add( cameraPY );\r\n\r\n\t\tvar cameraNY = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNY.up.set( 0, 0, - 1 );\r\n\t\tcameraNY.lookAt( new Vector3( 0, - 1, 0 ) );\r\n\t\tthis.add( cameraNY );\r\n\r\n\t\tvar cameraPZ = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPZ.up.set( 0, - 1, 0 );\r\n\t\tcameraPZ.lookAt( new Vector3( 0, 0, 1 ) );\r\n\t\tthis.add( cameraPZ );\r\n\r\n\t\tvar cameraNZ = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNZ.up.set( 0, - 1, 0 );\r\n\t\tcameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );\r\n\t\tthis.add( cameraNZ );\r\n\r\n\t\toptions = options || { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };\r\n\r\n\t\tthis.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );\r\n\t\tthis.renderTarget.texture.name = \"CubeCamera\";\r\n\r\n\t\tthis.update = function ( renderer, scene ) {\r\n\r\n\t\t\tif ( this.parent === null ) { this.updateMatrixWorld(); }\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\r\n\t\t\tvar renderTarget = this.renderTarget;\r\n\t\t\tvar generateMipmaps = renderTarget.texture.generateMipmaps;\r\n\r\n\t\t\trenderTarget.texture.generateMipmaps = false;\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 0 );\r\n\t\t\trenderer.render( scene, cameraPX );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 1 );\r\n\t\t\trenderer.render( scene, cameraNX );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 2 );\r\n\t\t\trenderer.render( scene, cameraPY );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 3 );\r\n\t\t\trenderer.render( scene, cameraNY );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 4 );\r\n\t\t\trenderer.render( scene, cameraPZ );\r\n\r\n\t\t\trenderTarget.texture.generateMipmaps = generateMipmaps;\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 5 );\r\n\t\t\trenderer.render( scene, cameraNZ );\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clear = function ( renderer, color, depth, stencil ) {\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\r\n\t\t\tvar renderTarget = this.renderTarget;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\trenderer.setRenderTarget( renderTarget, i );\r\n\r\n\t\t\t\trenderer.clear( color, depth, stencil );\r\n\r\n\t\t\t}\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tCubeCamera.prototype = Object.create( Object3D.prototype );\r\n\tCubeCamera.prototype.constructor = CubeCamera;\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction WebGLRenderTargetCube( width, height, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t}\r\n\r\n\tWebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );\r\n\tWebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;\r\n\r\n\tWebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;\r\n\r\n\tWebGLRenderTargetCube.prototype.fromEquirectangularTexture = function ( renderer, texture ) {\r\n\r\n\t\tthis.texture.type = texture.type;\r\n\t\tthis.texture.format = texture.format;\r\n\t\tthis.texture.encoding = texture.encoding;\r\n\r\n\t\tvar scene = new Scene();\r\n\r\n\t\tvar shader = {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\ttEquirect: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: [\r\n\r\n\t\t\t\t\"varying vec3 vWorldDirection;\",\r\n\r\n\t\t\t\t\"vec3 transformDirection( in vec3 dir, in mat4 matrix ) {\",\r\n\r\n\t\t\t\t\"\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\",\r\n\r\n\t\t\t\t\"}\",\r\n\r\n\t\t\t\t\"void main() {\",\r\n\r\n\t\t\t\t\"\tvWorldDirection = transformDirection( position, modelMatrix );\",\r\n\r\n\t\t\t\t\"\t#include \",\r\n\t\t\t\t\"\t#include \",\r\n\r\n\t\t\t\t\"}\"\r\n\r\n\t\t\t].join( '\\n' ),\r\n\r\n\t\t\tfragmentShader: [\r\n\r\n\t\t\t\t\"uniform sampler2D tEquirect;\",\r\n\r\n\t\t\t\t\"varying vec3 vWorldDirection;\",\r\n\r\n\t\t\t\t\"#define RECIPROCAL_PI 0.31830988618\",\r\n\t\t\t\t\"#define RECIPROCAL_PI2 0.15915494\",\r\n\r\n\t\t\t\t\"void main() {\",\r\n\r\n\t\t\t\t\"\tvec3 direction = normalize( vWorldDirection );\",\r\n\r\n\t\t\t\t\"\tvec2 sampleUV;\",\r\n\r\n\t\t\t\t\"\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\",\r\n\r\n\t\t\t\t\"\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\",\r\n\r\n\t\t\t\t\"\tgl_FragColor = texture2D( tEquirect, sampleUV );\",\r\n\r\n\t\t\t\t\"}\"\r\n\r\n\t\t\t].join( '\\n' ),\r\n\t\t};\r\n\r\n\t\tvar material = new ShaderMaterial( {\r\n\r\n\t\t\ttype: 'CubemapFromEquirect',\r\n\r\n\t\t\tuniforms: cloneUniforms( shader.uniforms ),\r\n\t\t\tvertexShader: shader.vertexShader,\r\n\t\t\tfragmentShader: shader.fragmentShader,\r\n\t\t\tside: BackSide,\r\n\t\t\tblending: NoBlending\r\n\r\n\t\t} );\r\n\r\n\t\tmaterial.uniforms.tEquirect.value = texture;\r\n\r\n\t\tvar mesh = new Mesh( new BoxBufferGeometry( 5, 5, 5 ), material );\r\n\r\n\t\tscene.add( mesh );\r\n\r\n\t\tvar camera = new CubeCamera( 1, 10, 1 );\r\n\r\n\t\tcamera.renderTarget = this;\r\n\t\tcamera.renderTarget.texture.name = 'CubeCameraTexture';\r\n\r\n\t\tcamera.update( renderer, scene );\r\n\r\n\t\tmesh.geometry.dispose();\r\n\t\tmesh.material.dispose();\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1 };\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\t\tthis.unpackAlignment = 1;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tDataTexture.prototype = Object.create( Texture.prototype );\r\n\tDataTexture.prototype.constructor = DataTexture;\r\n\r\n\tDataTexture.prototype.isDataTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _sphere$1 = new Sphere();\r\n\tvar _vector$6 = new Vector3();\r\n\r\n\tfunction Frustum( p0, p1, p2, p3, p4, p5 ) {\r\n\r\n\t\tthis.planes = [\r\n\r\n\t\t\t( p0 !== undefined ) ? p0 : new Plane(),\r\n\t\t\t( p1 !== undefined ) ? p1 : new Plane(),\r\n\t\t\t( p2 !== undefined ) ? p2 : new Plane(),\r\n\t\t\t( p3 !== undefined ) ? p3 : new Plane(),\r\n\t\t\t( p4 !== undefined ) ? p4 : new Plane(),\r\n\t\t\t( p5 !== undefined ) ? p5 : new Plane()\r\n\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tObject.assign( Frustum.prototype, {\r\n\r\n\t\tset: function ( p0, p1, p2, p3, p4, p5 ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tplanes[ 0 ].copy( p0 );\r\n\t\t\tplanes[ 1 ].copy( p1 );\r\n\t\t\tplanes[ 2 ].copy( p2 );\r\n\t\t\tplanes[ 3 ].copy( p3 );\r\n\t\t\tplanes[ 4 ].copy( p4 );\r\n\t\t\tplanes[ 5 ].copy( p5 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( frustum ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tplanes[ i ].copy( frustum.planes[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrix: function ( m ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\t\t\tvar me = m.elements;\r\n\t\t\tvar me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];\r\n\t\t\tvar me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];\r\n\t\t\tvar me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];\r\n\t\t\tvar me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];\r\n\r\n\t\t\tplanes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();\r\n\t\t\tplanes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();\r\n\t\t\tplanes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();\r\n\t\t\tplanes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();\r\n\t\t\tplanes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();\r\n\t\t\tplanes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsObject: function ( object ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );\r\n\r\n\t\t\treturn this.intersectsSphere( _sphere$1 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSprite: function ( sprite ) {\r\n\r\n\t\t\t_sphere$1.center.set( 0, 0, 0 );\r\n\t\t\t_sphere$1.radius = 0.7071067811865476;\r\n\t\t\t_sphere$1.applyMatrix4( sprite.matrixWorld );\r\n\r\n\t\t\treturn this.intersectsSphere( _sphere$1 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\t\t\tvar center = sphere.center;\r\n\t\t\tvar negRadius = - sphere.radius;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tvar distance = planes[ i ].distanceToPoint( center );\r\n\r\n\t\t\t\tif ( distance < negRadius ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tvar plane = planes[ i ];\r\n\r\n\t\t\t\t// corner at max distance\r\n\r\n\t\t\t\t_vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x;\r\n\t\t\t\t_vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y;\r\n\t\t\t\t_vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z;\r\n\r\n\t\t\t\tif ( plane.distanceToPoint( _vector$6 ) < 0 ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tif ( planes[ i ].distanceToPoint( point ) < 0 ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar alphamap_fragment = \"#ifdef USE_ALPHAMAP\\n\\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\\n#endif\";\n\n\tvar alphamap_pars_fragment = \"#ifdef USE_ALPHAMAP\\n\\tuniform sampler2D alphaMap;\\n#endif\";\n\n\tvar alphatest_fragment = \"#ifdef ALPHATEST\\n\\tif ( diffuseColor.a < ALPHATEST ) discard;\\n#endif\";\n\n\tvar 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( STANDARD )\\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\n\tvar aomap_pars_fragment = \"#ifdef USE_AOMAP\\n\\tuniform sampler2D aoMap;\\n\\tuniform float aoMapIntensity;\\n#endif\";\n\n\tvar begin_vertex = \"vec3 transformed = vec3( position );\";\n\n\tvar beginnormal_vertex = \"vec3 objectNormal = vec3( normal );\\n#ifdef USE_TANGENT\\n\\tvec3 objectTangent = vec3( tangent.xyz );\\n#endif\";\n\n\tvar bsdfs = \"vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\\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\\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\\n}\\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\\n\\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\\n\\tif( cutoffDistance > 0.0 ) {\\n\\t\\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\\n\\t}\\n\\treturn distanceFalloff;\\n#else\\n\\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\\n\\t\\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\\n\\t}\\n\\treturn 1.0;\\n#endif\\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}\\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\\n\\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\\n\\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\\n\\treturn Fr * fresnel + F0;\\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 vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\\n\\tfloat alpha = pow2( roughness );\\n\\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\\n\\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\\n\\tfloat dotNV = saturate( dot( normal, viewDir ) );\\n\\tfloat dotNH = saturate( dot( 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 dotNV = saturate( dot( N, V ) );\\n\\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\\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.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\\n\\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\\n\\tfloat v = a / b;\\n\\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - 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\\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\\n\\treturn vec3( result );\\n}\\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\\n\\tfloat dotNV = saturate( dot( normal, viewDir ) );\\n\\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\\n\\treturn specularColor * brdf.x + brdf.y;\\n}\\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\\n\\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\\n\\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\\n\\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\\n\\tvec3 FssEss = F * brdf.x + brdf.y;\\n\\tfloat Ess = brdf.x + brdf.y;\\n\\tfloat Ems = 1.0 - Ess;\\n\\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\\n\\tsingleScatter += FssEss;\\n\\tmultiScatter += Fms * Ems;\\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#if defined( USE_SHEEN )\\nfloat D_Charlie(float roughness, float NoH) {\\n\\tfloat invAlpha = 1.0 / roughness;\\n\\tfloat cos2h = NoH * NoH;\\n\\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\\n}\\nfloat V_Neubelt(float NoV, float NoL) {\\n\\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\\n}\\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\\n\\tvec3 N = geometry.normal;\\n\\tvec3 V = geometry.viewDir;\\n\\tvec3 H = normalize( V + L );\\n\\tfloat dotNH = saturate( dot( N, H ) );\\n\\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\\n}\\n#endif\";\n\n\tvar 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\\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\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\n\tvar clipping_planes_fragment = \"#if NUM_CLIPPING_PLANES > 0\\n\\tvec4 plane;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\\n\\t\\tplane = clippingPlanes[ i ];\\n\\t\\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\\n\\t}\\n\\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n\\t\\tbool clipped = true;\\n\\t\\t#pragma unroll_loop\\n\\t\\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n\\t\\t\\tplane = clippingPlanes[ i ];\\n\\t\\t\\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\\n\\t\\t}\\n\\t\\tif ( clipped ) discard;\\n\\t#endif\\n#endif\";\n\n\tvar clipping_planes_pars_fragment = \"#if NUM_CLIPPING_PLANES > 0\\n\\t#if ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\t\\tvarying vec3 vViewPosition;\\n\\t#endif\\n\\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\\n#endif\";\n\n\tvar clipping_planes_pars_vertex = \"#if NUM_CLIPPING_PLANES > 0 && ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\";\n\n\tvar clipping_planes_vertex = \"#if NUM_CLIPPING_PLANES > 0 && ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\tvViewPosition = - mvPosition.xyz;\\n#endif\";\n\n\tvar color_fragment = \"#ifdef USE_COLOR\\n\\tdiffuseColor.rgb *= vColor;\\n#endif\";\n\n\tvar color_pars_fragment = \"#ifdef USE_COLOR\\n\\tvarying vec3 vColor;\\n#endif\";\n\n\tvar color_pars_vertex = \"#ifdef USE_COLOR\\n\\tvarying vec3 vColor;\\n#endif\";\n\n\tvar color_vertex = \"#ifdef USE_COLOR\\n\\tvColor.xyz = color.xyz;\\n#endif\";\n\n\tvar 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#ifndef saturate\\n#define saturate(a) clamp( a, 0.0, 1.0 )\\n#endif\\n#define whiteComplement(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}\\n#ifdef HIGH_PRECISION\\n\\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\\n#else\\n\\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\\n\\tfloat precisionSafeLength( vec3 v ) {\\n\\t\\tfloat maxComponent = max3( abs( v ) );\\n\\t\\treturn length( v / maxComponent ) * maxComponent;\\n\\t}\\n#endif\\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#ifdef CLEARCOAT\\n\\tvec3 clearcoatNormal;\\n#endif\\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}\\nbool isPerspectiveMatrix( mat4 m ) {\\n return m[ 2 ][ 3 ] == - 1.0;\\n}\";\n\n\tvar cube_uv_reflection_fragment = \"#ifdef ENVMAP_TYPE_CUBE_UV\\n#define cubeUV_maxMipLevel 8.0\\n#define cubeUV_minMipLevel 4.0\\n#define cubeUV_maxTileSize 256.0\\n#define cubeUV_minTileSize 16.0\\nfloat getFace(vec3 direction) {\\n vec3 absDirection = abs(direction);\\n float face = -1.0;\\n if (absDirection.x > absDirection.z) {\\n if (absDirection.x > absDirection.y)\\n face = direction.x > 0.0 ? 0.0 : 3.0;\\n else\\n face = direction.y > 0.0 ? 1.0 : 4.0;\\n } else {\\n if (absDirection.z > absDirection.y)\\n face = direction.z > 0.0 ? 2.0 : 5.0;\\n else\\n face = direction.y > 0.0 ? 1.0 : 4.0;\\n }\\n return face;\\n}\\nvec2 getUV(vec3 direction, float face) {\\n vec2 uv;\\n if (face == 0.0) {\\n uv = vec2(-direction.z, direction.y) / abs(direction.x);\\n } else if (face == 1.0) {\\n uv = vec2(direction.x, -direction.z) / abs(direction.y);\\n } else if (face == 2.0) {\\n uv = direction.xy / abs(direction.z);\\n } else if (face == 3.0) {\\n uv = vec2(direction.z, direction.y) / abs(direction.x);\\n } else if (face == 4.0) {\\n uv = direction.xz / abs(direction.y);\\n } else {\\n uv = vec2(-direction.x, direction.y) / abs(direction.z);\\n }\\n return 0.5 * (uv + 1.0);\\n}\\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\\n float face = getFace(direction);\\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\\n mipInt = max(mipInt, cubeUV_minMipLevel);\\n float faceSize = exp2(mipInt);\\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\\n vec2 f = fract(uv);\\n uv += 0.5 - f;\\n if (face > 2.0) {\\n uv.y += faceSize;\\n face -= 3.0;\\n }\\n uv.x += face * faceSize;\\n if(mipInt < cubeUV_maxMipLevel){\\n uv.y += 2.0 * cubeUV_maxTileSize;\\n }\\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\\n uv *= texelSize;\\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.x += texelSize;\\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.y += texelSize;\\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.x -= texelSize;\\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n vec3 tm = mix(tl, tr, f.x);\\n vec3 bm = mix(bl, br, f.x);\\n return mix(tm, bm, f.y);\\n}\\n#define r0 1.0\\n#define v0 0.339\\n#define m0 -2.0\\n#define r1 0.8\\n#define v1 0.276\\n#define m1 -1.0\\n#define r4 0.4\\n#define v4 0.046\\n#define m4 2.0\\n#define r5 0.305\\n#define v5 0.016\\n#define m5 3.0\\n#define r6 0.21\\n#define v6 0.0038\\n#define m6 4.0\\nfloat roughnessToVariance(float roughness) {\\n float variance = 0.0;\\n if (roughness >= r1) {\\n variance = (r0 - roughness) * (v1 - v0) / (r0 - r1) + v0;\\n } else if (roughness >= r4) {\\n variance = (r1 - roughness) * (v4 - v1) / (r1 - r4) + v1;\\n } else if (roughness >= r5) {\\n variance = (r4 - roughness) * (v5 - v4) / (r4 - r5) + v4;\\n } else {\\n float roughness2 = roughness * roughness;\\n variance = 1.79 * roughness2 * roughness2;\\n }\\n return variance;\\n}\\nfloat varianceToRoughness(float variance) {\\n float roughness = 0.0;\\n if (variance >= v1) {\\n roughness = (v0 - variance) * (r1 - r0) / (v0 - v1) + r0;\\n } else if (variance >= v4) {\\n roughness = (v1 - variance) * (r4 - r1) / (v1 - v4) + r1;\\n } else if (variance >= v5) {\\n roughness = (v4 - variance) * (r5 - r4) / (v4 - v5) + r4;\\n } else {\\n roughness = pow(0.559 * variance, 0.25); }\\n return roughness;\\n}\\nfloat roughnessToMip(float roughness) {\\n float mip = 0.0;\\n if (roughness >= r1) {\\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\\n } else if (roughness >= r4) {\\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\\n } else if (roughness >= r5) {\\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\\n } else if (roughness >= r6) {\\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\\n } else {\\n mip = -2.0 * log2(1.16 * roughness); }\\n return mip;\\n}\\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\\n float mipF = fract(mip);\\n float mipInt = floor(mip);\\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\\n if (mipF == 0.0) {\\n return vec4(color0, 1.0);\\n } else {\\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\\n return vec4(mix(color0, color1, mipF), 1.0);\\n }\\n}\\n#endif\";\n\n\tvar defaultnormal_vertex = \"vec3 transformedNormal = objectNormal;\\n#ifdef USE_INSTANCING\\n\\ttransformedNormal = mat3( instanceMatrix ) * transformedNormal;\\n#endif\\ntransformedNormal = normalMatrix * transformedNormal;\\n#ifdef FLIP_SIDED\\n\\ttransformedNormal = - transformedNormal;\\n#endif\\n#ifdef USE_TANGENT\\n\\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\\n\\t#ifdef FLIP_SIDED\\n\\t\\ttransformedTangent = - transformedTangent;\\n\\t#endif\\n#endif\";\n\n\tvar displacementmap_pars_vertex = \"#ifdef USE_DISPLACEMENTMAP\\n\\tuniform sampler2D displacementMap;\\n\\tuniform float displacementScale;\\n\\tuniform float displacementBias;\\n#endif\";\n\n\tvar displacementmap_vertex = \"#ifdef USE_DISPLACEMENTMAP\\n\\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\\n#endif\";\n\n\tvar emissivemap_fragment = \"#ifdef USE_EMISSIVEMAP\\n\\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\\n\\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\\n\\ttotalEmissiveRadiance *= emissiveColor.rgb;\\n#endif\";\n\n\tvar emissivemap_pars_fragment = \"#ifdef USE_EMISSIVEMAP\\n\\tuniform sampler2D emissiveMap;\\n#endif\";\n\n\tvar encodings_fragment = \"gl_FragColor = linearToOutputTexel( gl_FragColor );\";\n\n\tvar 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.rgb, vec3( gammaFactor ) ), value.a );\\n}\\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\\n\\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\\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.a );\\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.a );\\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.rgb * value.a * maxRange, 1.0 );\\n}\\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\\n\\tfloat maxRGB = max( value.r, 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.r, 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 = cLogLuvM * value.rgb;\\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 = cLogLuvInverseM * Xp_Y_XYZp.rgb;\\n\\treturn vec4( max( vRGB, 0.0 ), 1.0 );\\n}\";\n\n\tvar envmap_fragment = \"#ifdef USE_ENVMAP\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvec3 cameraToFrag;\\n\\t\\t\\n\\t\\tif ( isOrthographic ) {\\n\\t\\t\\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\\n\\t\\t} else {\\n\\t\\t\\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\\n\\t\\t}\\n\\t\\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\\n\\t\\t#ifdef ENVMAP_MODE_REFLECTION\\n\\t\\t\\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\\n\\t\\t#else\\n\\t\\t\\tvec3 reflectVec = refract( cameraToFrag, 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_CUBE_UV )\\n\\t\\tvec4 envColor = textureCubeUV( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), 0.0 );\\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\\t#ifndef ENVMAP_TYPE_CUBE_UV\\n\\t\\tenvColor = envMapTexelToLinear( envColor );\\n\\t#endif\\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\n\tvar envmap_common_pars_fragment = \"#ifdef USE_ENVMAP\\n\\tuniform float envMapIntensity;\\n\\tuniform float flipEnvMap;\\n\\tuniform int maxMipLevel;\\n\\t#ifdef ENVMAP_TYPE_CUBE\\n\\t\\tuniform samplerCube envMap;\\n\\t#else\\n\\t\\tuniform sampler2D envMap;\\n\\t#endif\\n\\t\\n#endif\";\n\n\tvar envmap_pars_fragment = \"#ifdef USE_ENVMAP\\n\\tuniform float reflectivity;\\n\\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\\n\\t\\t#define ENV_WORLDPOS\\n\\t#endif\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvarying vec3 vWorldPosition;\\n\\t\\tuniform float refractionRatio;\\n\\t#else\\n\\t\\tvarying vec3 vReflect;\\n\\t#endif\\n#endif\";\n\n\tvar envmap_pars_vertex = \"#ifdef USE_ENVMAP\\n\\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\\n\\t\\t#define ENV_WORLDPOS\\n\\t#endif\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\t\\n\\t\\tvarying vec3 vWorldPosition;\\n\\t#else\\n\\t\\tvarying vec3 vReflect;\\n\\t\\tuniform float refractionRatio;\\n\\t#endif\\n#endif\";\n\n\tvar envmap_vertex = \"#ifdef USE_ENVMAP\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvWorldPosition = worldPosition.xyz;\\n\\t#else\\n\\t\\tvec3 cameraToVertex;\\n\\t\\tif ( isOrthographic ) { \\n\\t\\t\\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\\n\\t\\t} else {\\n\\t\\t\\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\\n\\t\\t}\\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\n\tvar fog_vertex = \"#ifdef USE_FOG\\n\\tfogDepth = -mvPosition.z;\\n#endif\";\n\n\tvar fog_pars_vertex = \"#ifdef USE_FOG\\n\\tvarying float fogDepth;\\n#endif\";\n\n\tvar fog_fragment = \"#ifdef USE_FOG\\n\\t#ifdef FOG_EXP2\\n\\t\\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\\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\n\tvar 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\n\tvar gradientmap_pars_fragment = \"#ifdef USE_GRADIENTMAP\\n\\tuniform sampler2D gradientMap;\\n#endif\\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\\n\\tfloat dotNL = dot( normal, lightDirection );\\n\\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\\n\\t#ifdef USE_GRADIENTMAP\\n\\t\\treturn texture2D( gradientMap, coord ).rgb;\\n\\t#else\\n\\t\\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\\n\\t#endif\\n}\";\n\n\tvar lightmap_fragment = \"#ifdef USE_LIGHTMAP\\n\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\\n#endif\";\n\n\tvar lightmap_pars_fragment = \"#ifdef USE_LIGHTMAP\\n\\tuniform sampler2D lightMap;\\n\\tuniform float lightMapIntensity;\\n#endif\";\n\n\tvar lights_lambert_vertex = \"vec3 diffuse = vec3( 1.0 );\\nGeometricContext geometry;\\ngeometry.position = mvPosition.xyz;\\ngeometry.normal = normalize( transformedNormal );\\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\\nGeometricContext backGeometry;\\nbackGeometry.position = geometry.position;\\nbackGeometry.normal = -geometry.normal;\\nbackGeometry.viewDir = geometry.viewDir;\\nvLightFront = vec3( 0.0 );\\nvIndirectFront = vec3( 0.0 );\\n#ifdef DOUBLE_SIDED\\n\\tvLightBack = vec3( 0.0 );\\n\\tvIndirectBack = vec3( 0.0 );\\n#endif\\nIncidentLight directLight;\\nfloat dotNL;\\nvec3 directLightColor_Diffuse;\\n#if NUM_POINT_LIGHTS > 0\\n\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\\n\\t\\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\\n\\t\\t#ifdef DOUBLE_SIDED\\n\\t\\t\\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\\n\\t\\t#endif\\n\\t}\\n#endif\";\n\n\tvar lights_pars_begin = \"uniform bool receiveShadow;\\nuniform vec3 ambientLightColor;\\nuniform vec3 lightProbe[ 9 ];\\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\\n\\tfloat x = normal.x, y = normal.y, z = normal.z;\\n\\tvec3 result = shCoefficients[ 0 ] * 0.886227;\\n\\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\\n\\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\\n\\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\\n\\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\\n\\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\\n\\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\\n\\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\\n\\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\\n\\treturn result;\\n}\\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\\n\\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\\n\\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\\n\\treturn irradiance;\\n}\\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 ltc_1;\\tuniform sampler2D ltc_2;\\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\n\tvar envmap_physical_pars_fragment = \"#if defined( USE_ENVMAP )\\n\\t#ifdef ENVMAP_MODE_REFRACTION\\n\\t\\tuniform float refractionRatio;\\n\\t#endif\\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( envMap, 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 roughness, const in int maxMIPLevel ) {\\n\\t\\tfloat maxMIPLevelScalar = float( maxMIPLevel );\\n\\t\\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\\n\\t\\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\\n\\t\\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\\n\\t}\\n\\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\\n\\t\\t#ifdef ENVMAP_MODE_REFLECTION\\n\\t\\t vec3 reflectVec = reflect( -viewDir, normal );\\n\\t\\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\\n\\t\\t#else\\n\\t\\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\\n\\t\\t#endif\\n\\t\\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\\n\\t\\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, 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( envMap, queryReflectVec, roughness );\\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\n\tvar lights_toon_fragment = \"ToonMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb;\\nmaterial.specularColor = specular;\\nmaterial.specularShininess = shininess;\\nmaterial.specularStrength = specularStrength;\";\n\n\tvar lights_toon_pars_fragment = \"varying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\nstruct ToonMaterial {\\n\\tvec3\\tdiffuseColor;\\n\\tvec3\\tspecularColor;\\n\\tfloat\\tspecularShininess;\\n\\tfloat\\tspecularStrength;\\n};\\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\\n\\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\\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_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\\n\\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\\n}\\n#define RE_Direct\\t\\t\\t\\tRE_Direct_Toon\\n#define RE_IndirectDiffuse\\t\\tRE_IndirectDiffuse_Toon\\n#define Material_LightProbeLOD( material )\\t(0)\";\n\n\tvar lights_phong_fragment = \"BlinnPhongMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb;\\nmaterial.specularColor = specular;\\nmaterial.specularShininess = shininess;\\nmaterial.specularStrength = specularStrength;\";\n\n\tvar 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\\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\\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\n\tvar lights_physical_fragment = \"PhysicalMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\\n#ifdef REFLECTIVITY\\n\\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\\n#else\\n\\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\\n#endif\\n#ifdef CLEARCOAT\\n\\tmaterial.clearcoat = saturate( clearcoat );\\tmaterial.clearcoatRoughness = max( clearcoatRoughness, 0.0525 );\\n\\tmaterial.clearcoatRoughness += geometryRoughness;\\n\\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\\n#endif\\n#ifdef USE_SHEEN\\n\\tmaterial.sheenColor = sheen;\\n#endif\";\n\n\tvar lights_physical_pars_fragment = \"struct PhysicalMaterial {\\n\\tvec3\\tdiffuseColor;\\n\\tfloat\\tspecularRoughness;\\n\\tvec3\\tspecularColor;\\n#ifdef CLEARCOAT\\n\\tfloat clearcoat;\\n\\tfloat clearcoatRoughness;\\n#endif\\n#ifdef USE_SHEEN\\n\\tvec3 sheenColor;\\n#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\\tvec4 t1 = texture2D( ltc_1, uv );\\n\\t\\tvec4 t2 = texture2D( ltc_2, uv );\\n\\t\\tmat3 mInv = mat3(\\n\\t\\t\\tvec3( t1.x, 0, t1.y ),\\n\\t\\t\\tvec3( 0, 1, 0 ),\\n\\t\\t\\tvec3( t1.z, 0, t1.w )\\n\\t\\t);\\n\\t\\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\\n\\t\\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\\n\\t\\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), 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#ifdef CLEARCOAT\\n\\t\\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\\n\\t\\tvec3 ccIrradiance = ccDotNL * directLight.color;\\n\\t\\t#ifndef PHYSICALLY_CORRECT_LIGHTS\\n\\t\\t\\tccIrradiance *= PI;\\n\\t\\t#endif\\n\\t\\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\\n\\t\\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\\n\\t#else\\n\\t\\tfloat clearcoatDHR = 0.0;\\n\\t#endif\\n\\t#ifdef USE_SHEEN\\n\\t\\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\\n\\t\\t\\tmaterial.specularRoughness,\\n\\t\\t\\tdirectLight.direction,\\n\\t\\t\\tgeometry,\\n\\t\\t\\tmaterial.sheenColor\\n\\t\\t);\\n\\t#else\\n\\t\\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\\n\\t#endif\\n\\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\\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 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\\n\\t#ifdef CLEARCOAT\\n\\t\\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\\n\\t\\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\\n\\t\\tfloat ccDotNL = ccDotNV;\\n\\t\\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\\n\\t#else\\n\\t\\tfloat clearcoatDHR = 0.0;\\n\\t#endif\\n\\tfloat clearcoatInv = 1.0 - clearcoatDHR;\\n\\tvec3 singleScattering = vec3( 0.0 );\\n\\tvec3 multiScattering = vec3( 0.0 );\\n\\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\\n\\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\\n\\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\\n\\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\\n\\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\\n\\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\\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\\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\n\tvar lights_fragment_begin = \"\\nGeometricContext geometry;\\ngeometry.position = - vViewPosition;\\ngeometry.normal = normal;\\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\\n#ifdef CLEARCOAT\\n\\tgeometry.clearcoatNormal = clearcoatNormal;\\n#endif\\nIncidentLight directLight;\\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\\n\\tPointLight pointLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\\n\\t\\tpointLight = pointLights[ i ];\\n\\t\\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( pointLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\\n\\t\\tspotLight = spotLights[ i ];\\n\\t\\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( spotLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\\n\\t\\tdirectionalLight = directionalLights[ i ];\\n\\t\\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( directionalLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\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 iblIrradiance = vec3( 0.0 );\\n\\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\\n\\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\\n\\t#if ( NUM_HEMI_LIGHTS > 0 )\\n\\t\\t#pragma unroll_loop\\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#endif\\n#if defined( RE_IndirectSpecular )\\n\\tvec3 radiance = vec3( 0.0 );\\n\\tvec3 clearcoatRadiance = vec3( 0.0 );\\n#endif\";\n\n\tvar lights_fragment_maps = \"#if defined( RE_IndirectDiffuse )\\n\\t#ifdef USE_LIGHTMAP\\n\\t\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\t\\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * 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 defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\\n\\t\\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\\n\\t#endif\\n#endif\\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\\n\\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\\n\\t#ifdef CLEARCOAT\\n\\t\\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\\n\\t#endif\\n#endif\";\n\n\tvar lights_fragment_end = \"#if defined( RE_IndirectDiffuse )\\n\\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\\n#endif\\n#if defined( RE_IndirectSpecular )\\n\\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\\n#endif\";\n\n\tvar logdepthbuf_fragment = \"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\\n\\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\\n#endif\";\n\n\tvar logdepthbuf_pars_fragment = \"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\\n\\tuniform float logDepthBufFC;\\n\\tvarying float vFragDepth;\\n\\tvarying float vIsPerspective;\\n#endif\";\n\n\tvar logdepthbuf_pars_vertex = \"#ifdef USE_LOGDEPTHBUF\\n\\t#ifdef USE_LOGDEPTHBUF_EXT\\n\\t\\tvarying float vFragDepth;\\n\\t\\tvarying float vIsPerspective;\\n\\t#else\\n\\t\\tuniform float logDepthBufFC;\\n\\t#endif\\n#endif\";\n\n\tvar logdepthbuf_vertex = \"#ifdef USE_LOGDEPTHBUF\\n\\t#ifdef USE_LOGDEPTHBUF_EXT\\n\\t\\tvFragDepth = 1.0 + gl_Position.w;\\n\\t\\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\\n\\t#else\\n\\t\\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\\n\\t\\t\\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\\n\\t\\t\\tgl_Position.z *= gl_Position.w;\\n\\t\\t}\\n\\t#endif\\n#endif\";\n\n\tvar map_fragment = \"#ifdef USE_MAP\\n\\tvec4 texelColor = texture2D( map, vUv );\\n\\ttexelColor = mapTexelToLinear( texelColor );\\n\\tdiffuseColor *= texelColor;\\n#endif\";\n\n\tvar map_pars_fragment = \"#ifdef USE_MAP\\n\\tuniform sampler2D map;\\n#endif\";\n\n\tvar map_particle_fragment = \"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\\n\\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\\n#endif\\n#ifdef USE_MAP\\n\\tvec4 mapTexel = texture2D( map, uv );\\n\\tdiffuseColor *= mapTexelToLinear( mapTexel );\\n#endif\\n#ifdef USE_ALPHAMAP\\n\\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\\n#endif\";\n\n\tvar map_particle_pars_fragment = \"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\\n\\tuniform mat3 uvTransform;\\n#endif\\n#ifdef USE_MAP\\n\\tuniform sampler2D map;\\n#endif\\n#ifdef USE_ALPHAMAP\\n\\tuniform sampler2D alphaMap;\\n#endif\";\n\n\tvar metalnessmap_fragment = \"float metalnessFactor = metalness;\\n#ifdef USE_METALNESSMAP\\n\\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\\n\\tmetalnessFactor *= texelMetalness.b;\\n#endif\";\n\n\tvar metalnessmap_pars_fragment = \"#ifdef USE_METALNESSMAP\\n\\tuniform sampler2D metalnessMap;\\n#endif\";\n\n\tvar morphnormal_vertex = \"#ifdef USE_MORPHNORMALS\\n\\tobjectNormal *= morphTargetBaseInfluence;\\n\\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\\n\\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\\n\\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\\n\\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\\n#endif\";\n\n\tvar morphtarget_pars_vertex = \"#ifdef USE_MORPHTARGETS\\n\\tuniform float morphTargetBaseInfluence;\\n\\t#ifndef USE_MORPHNORMALS\\n\\tuniform float morphTargetInfluences[ 8 ];\\n\\t#else\\n\\tuniform float morphTargetInfluences[ 4 ];\\n\\t#endif\\n#endif\";\n\n\tvar morphtarget_vertex = \"#ifdef USE_MORPHTARGETS\\n\\ttransformed *= morphTargetBaseInfluence;\\n\\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\\n\\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\\n\\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\\n\\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\\n\\t#ifndef USE_MORPHNORMALS\\n\\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\\n\\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\\n\\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\\n\\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\\n\\t#endif\\n#endif\";\n\n\tvar normal_fragment_begin = \"#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\\t#ifdef USE_TANGENT\\n\\t\\tvec3 tangent = normalize( vTangent );\\n\\t\\tvec3 bitangent = normalize( vBitangent );\\n\\t\\t#ifdef DOUBLE_SIDED\\n\\t\\t\\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\t\\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\t#endif\\n\\t\\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\\n\\t\\t\\tmat3 vTBN = mat3( tangent, bitangent, normal );\\n\\t\\t#endif\\n\\t#endif\\n#endif\\nvec3 geometryNormal = normal;\";\n\n\tvar normal_fragment_maps = \"#ifdef OBJECTSPACE_NORMALMAP\\n\\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\\n\\t#ifdef FLIP_SIDED\\n\\t\\tnormal = - normal;\\n\\t#endif\\n\\t#ifdef DOUBLE_SIDED\\n\\t\\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t#endif\\n\\tnormal = normalize( normalMatrix * normal );\\n#elif defined( TANGENTSPACE_NORMALMAP )\\n\\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\\n\\tmapN.xy *= normalScale;\\n\\t#ifdef USE_TANGENT\\n\\t\\tnormal = normalize( vTBN * mapN );\\n\\t#else\\n\\t\\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\\n\\t#endif\\n#elif defined( USE_BUMPMAP )\\n\\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\\n#endif\";\n\n\tvar normalmap_pars_fragment = \"#ifdef USE_NORMALMAP\\n\\tuniform sampler2D normalMap;\\n\\tuniform vec2 normalScale;\\n#endif\\n#ifdef OBJECTSPACE_NORMALMAP\\n\\tuniform mat3 normalMatrix;\\n#endif\\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\\n\\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\\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\\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\\n\\t\\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\\n\\t\\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\\n\\t\\tvec3 N = normalize( surf_norm );\\n\\t\\tmat3 tsn = mat3( S, T, N );\\n\\t\\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\treturn normalize( tsn * mapN );\\n\\t}\\n#endif\";\n\n\tvar clearcoat_normal_fragment_begin = \"#ifdef CLEARCOAT\\n\\tvec3 clearcoatNormal = geometryNormal;\\n#endif\";\n\n\tvar clearcoat_normal_fragment_maps = \"#ifdef USE_CLEARCOAT_NORMALMAP\\n\\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\\n\\tclearcoatMapN.xy *= clearcoatNormalScale;\\n\\t#ifdef USE_TANGENT\\n\\t\\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\\n\\t#else\\n\\t\\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\\n\\t#endif\\n#endif\";\n\n\tvar clearcoat_normalmap_pars_fragment = \"#ifdef USE_CLEARCOAT_NORMALMAP\\n\\tuniform sampler2D clearcoatNormalMap;\\n\\tuniform vec2 clearcoatNormalScale;\\n#endif\";\n\n\tvar 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}\\nvec4 pack2HalfToRGBA( vec2 v ) {\\n\\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\\n\\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\\n}\\nvec2 unpack2HalfToRGBA( vec4 v ) {\\n\\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\\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\n\tvar premultiplied_alpha_fragment = \"#ifdef PREMULTIPLIED_ALPHA\\n\\tgl_FragColor.rgb *= gl_FragColor.a;\\n#endif\";\n\n\tvar project_vertex = \"vec4 mvPosition = vec4( transformed, 1.0 );\\n#ifdef USE_INSTANCING\\n\\tmvPosition = instanceMatrix * mvPosition;\\n#endif\\nmvPosition = modelViewMatrix * mvPosition;\\ngl_Position = projectionMatrix * mvPosition;\";\n\n\tvar dithering_fragment = \"#ifdef DITHERING\\n\\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\\n#endif\";\n\n\tvar dithering_pars_fragment = \"#ifdef 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\n\tvar roughnessmap_fragment = \"float roughnessFactor = roughness;\\n#ifdef USE_ROUGHNESSMAP\\n\\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\\n\\troughnessFactor *= texelRoughness.g;\\n#endif\";\n\n\tvar roughnessmap_pars_fragment = \"#ifdef USE_ROUGHNESSMAP\\n\\tuniform sampler2D roughnessMap;\\n#endif\";\n\n\tvar shadowmap_pars_fragment = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\\n\\t\\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\\n\\t}\\n\\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\\n\\t\\treturn unpack2HalfToRGBA( texture2D( shadow, uv ) );\\n\\t}\\n\\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\\n\\t\\tfloat occlusion = 1.0;\\n\\t\\tvec2 distribution = texture2DDistribution( shadow, uv );\\n\\t\\tfloat hard_shadow = step( compare , distribution.x );\\n\\t\\tif (hard_shadow != 1.0 ) {\\n\\t\\t\\tfloat distance = compare - distribution.x ;\\n\\t\\t\\tfloat variance = max( 0.00000, distribution.y * distribution.y );\\n\\t\\t\\tfloat softness_probability = variance / (variance + distance * distance );\\t\\t\\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\\t\\t\\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\\n\\t\\t}\\n\\t\\treturn occlusion;\\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 ) + 0.5 ) * texelSize;\\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\\tfloat dx2 = dx0 / 2.0;\\n\\t\\t\\tfloat dy2 = dy0 / 2.0;\\n\\t\\t\\tfloat dx3 = dx1 / 2.0;\\n\\t\\t\\tfloat dy3 = dy1 / 2.0;\\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( dx2, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), 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( dx2, dy3 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), 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 / 17.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#elif defined( SHADOWMAP_TYPE_VSM )\\n\\t\\t\\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\\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 ) || defined( SHADOWMAP_TYPE_VSM )\\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\n\tvar shadowmap_pars_vertex = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t#endif\\n#endif\";\n\n\tvar shadowmap_vertex = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n#endif\";\n\n\tvar shadowmask_pars_fragment = \"float getShadowMask() {\\n\\tfloat shadow = 1.0;\\n\\t#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\tDirectionalLight directionalLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tdirectionalLight = directionalLights[ i ];\\n\\t\\tshadow *= all( bvec2( directionalLight.shadow, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\\n\\t}\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\tSpotLight spotLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tspotLight = spotLights[ i ];\\n\\t\\tshadow *= all( bvec2( spotLight.shadow, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\\n\\t}\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\tPointLight pointLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tpointLight = pointLights[ i ];\\n\\t\\tshadow *= all( bvec2( pointLight.shadow, receiveShadow ) ) ? 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\n\tvar 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\";\n\n\tvar skinning_pars_vertex = \"#ifdef USE_SKINNING\\n\\tuniform mat4 bindMatrix;\\n\\tuniform mat4 bindMatrixInverse;\\n\\t#ifdef BONE_TEXTURE\\n\\t\\tuniform highp 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\n\tvar 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\n\tvar 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\\t#ifdef USE_TANGENT\\n\\t\\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\\n\\t#endif\\n#endif\";\n\n\tvar 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\";\n\n\tvar specularmap_pars_fragment = \"#ifdef USE_SPECULARMAP\\n\\tuniform sampler2D specularMap;\\n#endif\";\n\n\tvar tonemapping_fragment = \"#if defined( TONE_MAPPING )\\n\\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\\n#endif\";\n\n\tvar tonemapping_pars_fragment = \"#ifndef saturate\\n#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}\\nvec3 ACESFilmicToneMapping( vec3 color ) {\\n\\tcolor *= toneMappingExposure;\\n\\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\\n}\";\n\n\tvar uv_pars_fragment = \"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\\n\\tvarying vec2 vUv;\\n#endif\";\n\n\tvar uv_pars_vertex = \"#ifdef USE_UV\\n\\t#ifdef UVS_VERTEX_ONLY\\n\\t\\tvec2 vUv;\\n\\t#else\\n\\t\\tvarying vec2 vUv;\\n\\t#endif\\n\\tuniform mat3 uvTransform;\\n#endif\";\n\n\tvar uv_vertex = \"#ifdef USE_UV\\n\\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\\n#endif\";\n\n\tvar uv2_pars_fragment = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tvarying vec2 vUv2;\\n#endif\";\n\n\tvar uv2_pars_vertex = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tattribute vec2 uv2;\\n\\tvarying vec2 vUv2;\\n\\tuniform mat3 uv2Transform;\\n#endif\";\n\n\tvar uv2_vertex = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\\n#endif\";\n\n\tvar worldpos_vertex = \"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\\n\\tvec4 worldPosition = vec4( transformed, 1.0 );\\n\\t#ifdef USE_INSTANCING\\n\\t\\tworldPosition = instanceMatrix * worldPosition;\\n\\t#endif\\n\\tworldPosition = modelMatrix * worldPosition;\\n#endif\";\n\n\tvar background_frag = \"uniform sampler2D t2D;\\nvarying vec2 vUv;\\nvoid main() {\\n\\tvec4 texColor = texture2D( t2D, vUv );\\n\\tgl_FragColor = mapTexelToLinear( texColor );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar background_vert = \"varying vec2 vUv;\\nuniform mat3 uvTransform;\\nvoid main() {\\n\\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\\n\\tgl_Position = vec4( position.xy, 1.0, 1.0 );\\n}\";\n\n\tvar cube_frag = \"#include \\nuniform float opacity;\\nvarying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvec3 vReflect = vWorldDirection;\\n\\t#include \\n\\tgl_FragColor = envColor;\\n\\tgl_FragColor.a *= opacity;\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar cube_vert = \"varying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvWorldDirection = transformDirection( position, modelMatrix );\\n\\t#include \\n\\t#include \\n\\tgl_Position.z = gl_Position.w;\\n}\";\n\n\tvar depth_frag = \"#if DEPTH_PACKING == 3200\\n\\tuniform float opacity;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( 1.0 );\\n\\t#if DEPTH_PACKING == 3200\\n\\t\\tdiffuseColor.a = opacity;\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#if DEPTH_PACKING == 3200\\n\\t\\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\\n\\t#elif DEPTH_PACKING == 3201\\n\\t\\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\\n\\t#endif\\n}\";\n\n\tvar depth_vert = \"#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#ifdef USE_DISPLACEMENTMAP\\n\\t\\t#include \\n\\t\\t#include \\n\\t\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar distanceRGBA_frag = \"#define DISTANCE\\nuniform vec3 referencePosition;\\nuniform float nearDistance;\\nuniform float farDistance;\\nvarying vec3 vWorldPosition;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main () {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( 1.0 );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\tfloat dist = length( vWorldPosition - referencePosition );\\n\\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\\n\\tdist = saturate( dist );\\n\\tgl_FragColor = packDepthToRGBA( dist );\\n}\";\n\n\tvar distanceRGBA_vert = \"#define DISTANCE\\nvarying vec3 vWorldPosition;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#ifdef USE_DISPLACEMENTMAP\\n\\t\\t#include \\n\\t\\t#include \\n\\t\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvWorldPosition = worldPosition.xyz;\\n}\";\n\n\tvar equirect_frag = \"uniform sampler2D tEquirect;\\nvarying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvec3 direction = normalize( vWorldDirection );\\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\\tvec4 texColor = texture2D( tEquirect, sampleUV );\\n\\tgl_FragColor = mapTexelToLinear( texColor );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar equirect_vert = \"varying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvWorldDirection = transformDirection( position, modelMatrix );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar linedashed_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\nuniform float dashSize;\\nuniform float totalSize;\\nvarying float vLineDistance;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar linedashed_vert = \"uniform float scale;\\nattribute float lineDistance;\\nvarying float vLineDistance;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvLineDistance = scale * lineDistance;\\n\\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\\n\\tgl_Position = projectionMatrix * mvPosition;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshbasic_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\\n\\t#ifdef USE_LIGHTMAP\\n\\t\\n\\t\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\t\\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\\n\\t#else\\n\\t\\treflectedLight.indirectDiffuse += vec3( 1.0 );\\n\\t#endif\\n\\t#include \\n\\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\\n\\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshbasic_vert = \"#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#ifdef USE_ENVMAP\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshlambert_frag = \"uniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform float opacity;\\nvarying vec3 vLightFront;\\nvarying vec3 vIndirectFront;\\n#ifdef DOUBLE_SIDED\\n\\tvarying vec3 vLightBack;\\n\\tvarying vec3 vIndirectBack;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\\n\\t#ifdef DOUBLE_SIDED\\n\\t\\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\\n\\t#else\\n\\t\\treflectedLight.indirectDiffuse += vIndirectFront;\\n\\t#endif\\n\\t#include \\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 \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshlambert_vert = \"#define LAMBERT\\nvarying vec3 vLightFront;\\nvarying vec3 vIndirectFront;\\n#ifdef DOUBLE_SIDED\\n\\tvarying vec3 vLightBack;\\n\\tvarying vec3 vIndirectBack;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshmatcap_frag = \"#define MATCAP\\nuniform vec3 diffuse;\\nuniform float opacity;\\nuniform sampler2D matcap;\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 viewDir = normalize( vViewPosition );\\n\\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\\n\\tvec3 y = cross( viewDir, x );\\n\\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\\n\\t#ifdef USE_MATCAP\\n\\t\\tvec4 matcapColor = texture2D( matcap, uv );\\n\\t\\tmatcapColor = matcapTexelToLinear( matcapColor );\\n\\t#else\\n\\t\\tvec4 matcapColor = vec4( 1.0 );\\n\\t#endif\\n\\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshmatcap_vert = \"#define MATCAP\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#ifndef FLAT_SHADED\\n\\t\\tvNormal = normalize( transformedNormal );\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n}\";\n\n\tvar meshtoon_frag = \"#define TOON\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform vec3 specular;\\nuniform float shininess;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshtoon_vert = \"#define TOON\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphong_frag = \"#define PHONG\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform vec3 specular;\\nuniform float shininess;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphong_vert = \"#define PHONG\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphysical_frag = \"#define STANDARD\\n#ifdef PHYSICAL\\n\\t#define REFLECTIVITY\\n\\t#define CLEARCOAT\\n\\t#define TRANSPARENCY\\n#endif\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform float roughness;\\nuniform float metalness;\\nuniform float opacity;\\n#ifdef TRANSPARENCY\\n\\tuniform float transparency;\\n#endif\\n#ifdef REFLECTIVITY\\n\\tuniform float reflectivity;\\n#endif\\n#ifdef CLEARCOAT\\n\\tuniform float clearcoat;\\n\\tuniform float clearcoatRoughness;\\n#endif\\n#ifdef USE_SHEEN\\n\\tuniform vec3 sheen;\\n#endif\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\t#ifdef TRANSPARENCY\\n\\t\\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\\n\\t#endif\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphysical_vert = \"#define STANDARD\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n\\t#ifdef USE_TANGENT\\n\\t\\tvTangent = normalize( transformedTangent );\\n\\t\\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\\n\\t#endif\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar normal_frag = \"#define NORMAL\\nuniform float opacity;\\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\\n}\";\n\n\tvar normal_vert = \"#define NORMAL\\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n\\t#ifdef USE_TANGENT\\n\\t\\tvTangent = normalize( transformedTangent );\\n\\t\\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\\n\\t#endif\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvViewPosition = - mvPosition.xyz;\\n#endif\\n}\";\n\n\tvar points_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec3 outgoingLight = vec3( 0.0 );\\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar points_vert = \"uniform float size;\\nuniform float scale;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tgl_PointSize = size;\\n\\t#ifdef USE_SIZEATTENUATION\\n\\t\\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\\n\\t\\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar shadow_frag = \"uniform vec3 color;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\\n\\t#include \\n}\";\n\n\tvar shadow_vert = \"#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar sprite_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec3 outgoingLight = vec3( 0.0 );\\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar sprite_vert = \"uniform float rotation;\\nuniform vec2 center;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\\n\\tvec2 scale;\\n\\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\\n\\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\\n\\t#ifndef USE_SIZEATTENUATION\\n\\t\\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\\n\\t\\tif ( isPerspective ) scale *= - mvPosition.z;\\n\\t#endif\\n\\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\\n\\tvec2 rotatedPosition;\\n\\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\\n\\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\\n\\tmvPosition.xy += rotatedPosition;\\n\\tgl_Position = projectionMatrix * mvPosition;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar ShaderChunk = {\r\n\t\talphamap_fragment: alphamap_fragment,\r\n\t\talphamap_pars_fragment: alphamap_pars_fragment,\r\n\t\talphatest_fragment: alphatest_fragment,\r\n\t\taomap_fragment: aomap_fragment,\r\n\t\taomap_pars_fragment: aomap_pars_fragment,\r\n\t\tbegin_vertex: begin_vertex,\r\n\t\tbeginnormal_vertex: beginnormal_vertex,\r\n\t\tbsdfs: bsdfs,\r\n\t\tbumpmap_pars_fragment: bumpmap_pars_fragment,\r\n\t\tclipping_planes_fragment: clipping_planes_fragment,\r\n\t\tclipping_planes_pars_fragment: clipping_planes_pars_fragment,\r\n\t\tclipping_planes_pars_vertex: clipping_planes_pars_vertex,\r\n\t\tclipping_planes_vertex: clipping_planes_vertex,\r\n\t\tcolor_fragment: color_fragment,\r\n\t\tcolor_pars_fragment: color_pars_fragment,\r\n\t\tcolor_pars_vertex: color_pars_vertex,\r\n\t\tcolor_vertex: color_vertex,\r\n\t\tcommon: common,\r\n\t\tcube_uv_reflection_fragment: cube_uv_reflection_fragment,\r\n\t\tdefaultnormal_vertex: defaultnormal_vertex,\r\n\t\tdisplacementmap_pars_vertex: displacementmap_pars_vertex,\r\n\t\tdisplacementmap_vertex: displacementmap_vertex,\r\n\t\temissivemap_fragment: emissivemap_fragment,\r\n\t\temissivemap_pars_fragment: emissivemap_pars_fragment,\r\n\t\tencodings_fragment: encodings_fragment,\r\n\t\tencodings_pars_fragment: encodings_pars_fragment,\r\n\t\tenvmap_fragment: envmap_fragment,\r\n\t\tenvmap_common_pars_fragment: envmap_common_pars_fragment,\r\n\t\tenvmap_pars_fragment: envmap_pars_fragment,\r\n\t\tenvmap_pars_vertex: envmap_pars_vertex,\r\n\t\tenvmap_physical_pars_fragment: envmap_physical_pars_fragment,\r\n\t\tenvmap_vertex: envmap_vertex,\r\n\t\tfog_vertex: fog_vertex,\r\n\t\tfog_pars_vertex: fog_pars_vertex,\r\n\t\tfog_fragment: fog_fragment,\r\n\t\tfog_pars_fragment: fog_pars_fragment,\r\n\t\tgradientmap_pars_fragment: gradientmap_pars_fragment,\r\n\t\tlightmap_fragment: lightmap_fragment,\r\n\t\tlightmap_pars_fragment: lightmap_pars_fragment,\r\n\t\tlights_lambert_vertex: lights_lambert_vertex,\r\n\t\tlights_pars_begin: lights_pars_begin,\r\n\t\tlights_toon_fragment: lights_toon_fragment,\r\n\t\tlights_toon_pars_fragment: lights_toon_pars_fragment,\r\n\t\tlights_phong_fragment: lights_phong_fragment,\r\n\t\tlights_phong_pars_fragment: lights_phong_pars_fragment,\r\n\t\tlights_physical_fragment: lights_physical_fragment,\r\n\t\tlights_physical_pars_fragment: lights_physical_pars_fragment,\r\n\t\tlights_fragment_begin: lights_fragment_begin,\r\n\t\tlights_fragment_maps: lights_fragment_maps,\r\n\t\tlights_fragment_end: lights_fragment_end,\r\n\t\tlogdepthbuf_fragment: logdepthbuf_fragment,\r\n\t\tlogdepthbuf_pars_fragment: logdepthbuf_pars_fragment,\r\n\t\tlogdepthbuf_pars_vertex: logdepthbuf_pars_vertex,\r\n\t\tlogdepthbuf_vertex: logdepthbuf_vertex,\r\n\t\tmap_fragment: map_fragment,\r\n\t\tmap_pars_fragment: map_pars_fragment,\r\n\t\tmap_particle_fragment: map_particle_fragment,\r\n\t\tmap_particle_pars_fragment: map_particle_pars_fragment,\r\n\t\tmetalnessmap_fragment: metalnessmap_fragment,\r\n\t\tmetalnessmap_pars_fragment: metalnessmap_pars_fragment,\r\n\t\tmorphnormal_vertex: morphnormal_vertex,\r\n\t\tmorphtarget_pars_vertex: morphtarget_pars_vertex,\r\n\t\tmorphtarget_vertex: morphtarget_vertex,\r\n\t\tnormal_fragment_begin: normal_fragment_begin,\r\n\t\tnormal_fragment_maps: normal_fragment_maps,\r\n\t\tnormalmap_pars_fragment: normalmap_pars_fragment,\r\n\t\tclearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,\r\n\t\tclearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,\r\n\t\tclearcoat_normalmap_pars_fragment: clearcoat_normalmap_pars_fragment,\r\n\t\tpacking: packing,\r\n\t\tpremultiplied_alpha_fragment: premultiplied_alpha_fragment,\r\n\t\tproject_vertex: project_vertex,\r\n\t\tdithering_fragment: dithering_fragment,\r\n\t\tdithering_pars_fragment: dithering_pars_fragment,\r\n\t\troughnessmap_fragment: roughnessmap_fragment,\r\n\t\troughnessmap_pars_fragment: roughnessmap_pars_fragment,\r\n\t\tshadowmap_pars_fragment: shadowmap_pars_fragment,\r\n\t\tshadowmap_pars_vertex: shadowmap_pars_vertex,\r\n\t\tshadowmap_vertex: shadowmap_vertex,\r\n\t\tshadowmask_pars_fragment: shadowmask_pars_fragment,\r\n\t\tskinbase_vertex: skinbase_vertex,\r\n\t\tskinning_pars_vertex: skinning_pars_vertex,\r\n\t\tskinning_vertex: skinning_vertex,\r\n\t\tskinnormal_vertex: skinnormal_vertex,\r\n\t\tspecularmap_fragment: specularmap_fragment,\r\n\t\tspecularmap_pars_fragment: specularmap_pars_fragment,\r\n\t\ttonemapping_fragment: tonemapping_fragment,\r\n\t\ttonemapping_pars_fragment: tonemapping_pars_fragment,\r\n\t\tuv_pars_fragment: uv_pars_fragment,\r\n\t\tuv_pars_vertex: uv_pars_vertex,\r\n\t\tuv_vertex: uv_vertex,\r\n\t\tuv2_pars_fragment: uv2_pars_fragment,\r\n\t\tuv2_pars_vertex: uv2_pars_vertex,\r\n\t\tuv2_vertex: uv2_vertex,\r\n\t\tworldpos_vertex: worldpos_vertex,\r\n\r\n\t\tbackground_frag: background_frag,\r\n\t\tbackground_vert: background_vert,\r\n\t\tcube_frag: cube_frag,\r\n\t\tcube_vert: cube_vert,\r\n\t\tdepth_frag: depth_frag,\r\n\t\tdepth_vert: depth_vert,\r\n\t\tdistanceRGBA_frag: distanceRGBA_frag,\r\n\t\tdistanceRGBA_vert: distanceRGBA_vert,\r\n\t\tequirect_frag: equirect_frag,\r\n\t\tequirect_vert: equirect_vert,\r\n\t\tlinedashed_frag: linedashed_frag,\r\n\t\tlinedashed_vert: linedashed_vert,\r\n\t\tmeshbasic_frag: meshbasic_frag,\r\n\t\tmeshbasic_vert: meshbasic_vert,\r\n\t\tmeshlambert_frag: meshlambert_frag,\r\n\t\tmeshlambert_vert: meshlambert_vert,\r\n\t\tmeshmatcap_frag: meshmatcap_frag,\r\n\t\tmeshmatcap_vert: meshmatcap_vert,\r\n\t\tmeshtoon_frag: meshtoon_frag,\r\n\t\tmeshtoon_vert: meshtoon_vert,\r\n\t\tmeshphong_frag: meshphong_frag,\r\n\t\tmeshphong_vert: meshphong_vert,\r\n\t\tmeshphysical_frag: meshphysical_frag,\r\n\t\tmeshphysical_vert: meshphysical_vert,\r\n\t\tnormal_frag: normal_frag,\r\n\t\tnormal_vert: normal_vert,\r\n\t\tpoints_frag: points_frag,\r\n\t\tpoints_vert: points_vert,\r\n\t\tshadow_frag: shadow_frag,\r\n\t\tshadow_vert: shadow_vert,\r\n\t\tsprite_frag: sprite_frag,\r\n\t\tsprite_vert: sprite_vert\r\n\t};\n\n\t/**\r\n\t * Uniforms library for shared webgl shaders\r\n\t */\r\n\r\n\tvar UniformsLib = {\r\n\r\n\t\tcommon: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\r\n\t\t\tmap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() },\r\n\t\t\tuv2Transform: { value: new Matrix3() },\r\n\r\n\t\t\talphaMap: { value: null },\r\n\r\n\t\t},\r\n\r\n\t\tspecularmap: {\r\n\r\n\t\t\tspecularMap: { value: null },\r\n\r\n\t\t},\r\n\r\n\t\tenvmap: {\r\n\r\n\t\t\tenvMap: { value: null },\r\n\t\t\tflipEnvMap: { value: - 1 },\r\n\t\t\treflectivity: { value: 1.0 },\r\n\t\t\trefractionRatio: { value: 0.98 },\r\n\t\t\tmaxMipLevel: { value: 0 }\r\n\r\n\t\t},\r\n\r\n\t\taomap: {\r\n\r\n\t\t\taoMap: { value: null },\r\n\t\t\taoMapIntensity: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\tlightmap: {\r\n\r\n\t\t\tlightMap: { value: null },\r\n\t\t\tlightMapIntensity: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\temissivemap: {\r\n\r\n\t\t\temissiveMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tbumpmap: {\r\n\r\n\t\t\tbumpMap: { value: null },\r\n\t\t\tbumpScale: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\tnormalmap: {\r\n\r\n\t\t\tnormalMap: { value: null },\r\n\t\t\tnormalScale: { value: new Vector2( 1, 1 ) }\r\n\r\n\t\t},\r\n\r\n\t\tdisplacementmap: {\r\n\r\n\t\t\tdisplacementMap: { value: null },\r\n\t\t\tdisplacementScale: { value: 1 },\r\n\t\t\tdisplacementBias: { value: 0 }\r\n\r\n\t\t},\r\n\r\n\t\troughnessmap: {\r\n\r\n\t\t\troughnessMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tmetalnessmap: {\r\n\r\n\t\t\tmetalnessMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tgradientmap: {\r\n\r\n\t\t\tgradientMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tfog: {\r\n\r\n\t\t\tfogDensity: { value: 0.00025 },\r\n\t\t\tfogNear: { value: 1 },\r\n\t\t\tfogFar: { value: 2000 },\r\n\t\t\tfogColor: { value: new Color( 0xffffff ) }\r\n\r\n\t\t},\r\n\r\n\t\tlights: {\r\n\r\n\t\t\tambientLightColor: { value: [] },\r\n\r\n\t\t\tlightProbe: { value: [] },\r\n\r\n\t\t\tdirectionalLights: { value: [], properties: {\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tcolor: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {}\r\n\t\t\t} },\r\n\r\n\t\t\tdirectionalShadowMap: { value: [] },\r\n\t\t\tdirectionalShadowMatrix: { value: [] },\r\n\r\n\t\t\tspotLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tdistance: {},\r\n\t\t\t\tconeCos: {},\r\n\t\t\t\tpenumbraCos: {},\r\n\t\t\t\tdecay: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {}\r\n\t\t\t} },\r\n\r\n\t\t\tspotShadowMap: { value: [] },\r\n\t\t\tspotShadowMatrix: { value: [] },\r\n\r\n\t\t\tpointLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\tdecay: {},\r\n\t\t\t\tdistance: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {},\r\n\t\t\t\tshadowCameraNear: {},\r\n\t\t\t\tshadowCameraFar: {}\r\n\t\t\t} },\r\n\r\n\t\t\tpointShadowMap: { value: [] },\r\n\t\t\tpointShadowMatrix: { value: [] },\r\n\r\n\t\t\themisphereLights: { value: [], properties: {\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tskyColor: {},\r\n\t\t\t\tgroundColor: {}\r\n\t\t\t} },\r\n\r\n\t\t\t// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src\r\n\t\t\trectAreaLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\twidth: {},\r\n\t\t\t\theight: {}\r\n\t\t\t} }\r\n\r\n\t\t},\r\n\r\n\t\tpoints: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\t\t\tsize: { value: 1.0 },\r\n\t\t\tscale: { value: 1.0 },\r\n\t\t\tmap: { value: null },\r\n\t\t\talphaMap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() }\r\n\r\n\t\t},\r\n\r\n\t\tsprite: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\t\t\tcenter: { value: new Vector2( 0.5, 0.5 ) },\r\n\t\t\trotation: { value: 0.0 },\r\n\t\t\tmap: { value: null },\r\n\t\t\talphaMap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() }\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t */\r\n\r\n\tvar ShaderLib = {\r\n\r\n\t\tbasic: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshbasic_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshbasic_frag\r\n\r\n\t\t},\r\n\r\n\t\tlambert: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshlambert_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshlambert_frag\r\n\r\n\t\t},\r\n\r\n\t\tphong: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\tspecular: { value: new Color( 0x111111 ) },\r\n\t\t\t\t\tshininess: { value: 30 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshphong_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshphong_frag\r\n\r\n\t\t},\r\n\r\n\t\tstandard: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.roughnessmap,\r\n\t\t\t\tUniformsLib.metalnessmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\troughness: { value: 0.5 },\r\n\t\t\t\t\tmetalness: { value: 0.5 },\r\n\t\t\t\t\tenvMapIntensity: { value: 1 } // temporary\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshphysical_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshphysical_frag\r\n\r\n\t\t},\r\n\r\n\t\ttoon: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.gradientmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\tspecular: { value: new Color( 0x111111 ) },\r\n\t\t\t\t\tshininess: { value: 30 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshtoon_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshtoon_frag\r\n\r\n\t\t},\r\n\r\n\t\tmatcap: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tmatcap: { value: null }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshmatcap_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshmatcap_frag\r\n\r\n\t\t},\r\n\r\n\t\tpoints: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.points,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.points_vert,\r\n\t\t\tfragmentShader: ShaderChunk.points_frag\r\n\r\n\t\t},\r\n\r\n\t\tdashed: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tscale: { value: 1 },\r\n\t\t\t\t\tdashSize: { value: 1 },\r\n\t\t\t\t\ttotalSize: { value: 2 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.linedashed_vert,\r\n\t\t\tfragmentShader: ShaderChunk.linedashed_frag\r\n\r\n\t\t},\r\n\r\n\t\tdepth: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.displacementmap\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.depth_vert,\r\n\t\t\tfragmentShader: ShaderChunk.depth_frag\r\n\r\n\t\t},\r\n\r\n\t\tnormal: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\t{\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.normal_vert,\r\n\t\t\tfragmentShader: ShaderChunk.normal_frag\r\n\r\n\t\t},\r\n\r\n\t\tsprite: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.sprite,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.sprite_vert,\r\n\t\t\tfragmentShader: ShaderChunk.sprite_frag\r\n\r\n\t\t},\r\n\r\n\t\tbackground: {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\tuvTransform: { value: new Matrix3() },\r\n\t\t\t\tt2D: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: ShaderChunk.background_vert,\r\n\t\t\tfragmentShader: ShaderChunk.background_frag\r\n\r\n\t\t},\r\n\t\t/* -------------------------------------------------------------------------\r\n\t\t//\tCube map shader\r\n\t\t ------------------------------------------------------------------------- */\r\n\r\n\t\tcube: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\t{\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.cube_vert,\r\n\t\t\tfragmentShader: ShaderChunk.cube_frag\r\n\r\n\t\t},\r\n\r\n\t\tequirect: {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\ttEquirect: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: ShaderChunk.equirect_vert,\r\n\t\t\tfragmentShader: ShaderChunk.equirect_frag\r\n\r\n\t\t},\r\n\r\n\t\tdistanceRGBA: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\t{\r\n\t\t\t\t\treferencePosition: { value: new Vector3() },\r\n\t\t\t\t\tnearDistance: { value: 1 },\r\n\t\t\t\t\tfarDistance: { value: 1000 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.distanceRGBA_vert,\r\n\t\t\tfragmentShader: ShaderChunk.distanceRGBA_frag\r\n\r\n\t\t},\r\n\r\n\t\tshadow: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tcolor: { value: new Color( 0x00000 ) },\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t} ] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.shadow_vert,\r\n\t\t\tfragmentShader: ShaderChunk.shadow_frag\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tShaderLib.physical = {\r\n\r\n\t\tuniforms: mergeUniforms( [\r\n\t\t\tShaderLib.standard.uniforms,\r\n\t\t\t{\r\n\t\t\t\ttransparency: { value: 0 },\r\n\t\t\t\tclearcoat: { value: 0 },\r\n\t\t\t\tclearcoatRoughness: { value: 0 },\r\n\t\t\t\tsheen: { value: new Color( 0x000000 ) },\r\n\t\t\t\tclearcoatNormalScale: { value: new Vector2( 1, 1 ) },\r\n\t\t\t\tclearcoatNormalMap: { value: null },\r\n\t\t\t}\r\n\t\t] ),\r\n\r\n\t\tvertexShader: ShaderChunk.meshphysical_vert,\r\n\t\tfragmentShader: ShaderChunk.meshphysical_frag\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLAnimation() {\r\n\r\n\t\tvar context = null;\r\n\t\tvar isAnimating = false;\r\n\t\tvar animationLoop = null;\r\n\r\n\t\tfunction onAnimationFrame( time, frame ) {\r\n\r\n\t\t\tif ( isAnimating === false ) { return; }\r\n\r\n\t\t\tanimationLoop( time, frame );\r\n\r\n\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tstart: function () {\r\n\r\n\t\t\t\tif ( isAnimating === true ) { return; }\r\n\t\t\t\tif ( animationLoop === null ) { return; }\r\n\r\n\t\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\r\n\r\n\t\t\t\tisAnimating = true;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tstop: function () {\r\n\r\n\t\t\t\tisAnimating = false;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tsetAnimationLoop: function ( callback ) {\r\n\r\n\t\t\t\tanimationLoop = callback;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tsetContext: function ( value ) {\r\n\r\n\t\t\t\tcontext = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLAttributes( gl ) {\r\n\r\n\t\tvar buffers = new WeakMap();\r\n\r\n\t\tfunction createBuffer( attribute, bufferType ) {\r\n\r\n\t\t\tvar array = attribute.array;\r\n\t\t\tvar usage = attribute.usage;\r\n\r\n\t\t\tvar buffer = gl.createBuffer();\r\n\r\n\t\t\tgl.bindBuffer( bufferType, buffer );\r\n\t\t\tgl.bufferData( bufferType, array, usage );\r\n\r\n\t\t\tattribute.onUploadCallback();\r\n\r\n\t\t\tvar type = 5126;\r\n\r\n\t\t\tif ( array instanceof Float32Array ) {\r\n\r\n\t\t\t\ttype = 5126;\r\n\r\n\t\t\t} else if ( array instanceof Float64Array ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );\r\n\r\n\t\t\t} else if ( array instanceof Uint16Array ) {\r\n\r\n\t\t\t\ttype = 5123;\r\n\r\n\t\t\t} else if ( array instanceof Int16Array ) {\r\n\r\n\t\t\t\ttype = 5122;\r\n\r\n\t\t\t} else if ( array instanceof Uint32Array ) {\r\n\r\n\t\t\t\ttype = 5125;\r\n\r\n\t\t\t} else if ( array instanceof Int32Array ) {\r\n\r\n\t\t\t\ttype = 5124;\r\n\r\n\t\t\t} else if ( array instanceof Int8Array ) {\r\n\r\n\t\t\t\ttype = 5120;\r\n\r\n\t\t\t} else if ( array instanceof Uint8Array ) {\r\n\r\n\t\t\t\ttype = 5121;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tbuffer: buffer,\r\n\t\t\t\ttype: type,\r\n\t\t\t\tbytesPerElement: array.BYTES_PER_ELEMENT,\r\n\t\t\t\tversion: attribute.version\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateBuffer( buffer, attribute, bufferType ) {\r\n\r\n\t\t\tvar array = attribute.array;\r\n\t\t\tvar updateRange = attribute.updateRange;\r\n\r\n\t\t\tgl.bindBuffer( bufferType, buffer );\r\n\r\n\t\t\tif ( updateRange.count === - 1 ) {\r\n\r\n\t\t\t\t// Not using update ranges\r\n\r\n\t\t\t\tgl.bufferSubData( bufferType, 0, array );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\r\n\t\t\t\t\tarray.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );\r\n\r\n\t\t\t\tupdateRange.count = - 1; // reset range\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction get( attribute ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\treturn buffers.get( attribute );\r\n\r\n\t\t}\r\n\r\n\t\tfunction remove( attribute ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\tvar data = buffers.get( attribute );\r\n\r\n\t\t\tif ( data ) {\r\n\r\n\t\t\t\tgl.deleteBuffer( data.buffer );\r\n\r\n\t\t\t\tbuffers.delete( attribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( attribute, bufferType ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\tvar data = buffers.get( attribute );\r\n\r\n\t\t\tif ( data === undefined ) {\r\n\r\n\t\t\t\tbuffers.set( attribute, createBuffer( attribute, bufferType ) );\r\n\r\n\t\t\t} else if ( data.version < attribute.version ) {\r\n\r\n\t\t\t\tupdateBuffer( data.buffer, attribute, bufferType );\r\n\r\n\t\t\t\tdata.version = attribute.version;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: get,\r\n\t\t\tremove: remove,\r\n\t\t\tupdate: update\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// PlaneGeometry\r\n\r\n\tfunction PlaneGeometry( width, height, widthSegments, heightSegments ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'PlaneGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\twidth: width,\r\n\t\t\theight: height,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tPlaneGeometry.prototype = Object.create( Geometry.prototype );\r\n\tPlaneGeometry.prototype.constructor = PlaneGeometry;\r\n\r\n\t// PlaneBufferGeometry\r\n\r\n\tfunction PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'PlaneBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\twidth: width,\r\n\t\t\theight: height,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments\r\n\t\t};\r\n\r\n\t\twidth = width || 1;\r\n\t\theight = height || 1;\r\n\r\n\t\tvar width_half = width / 2;\r\n\t\tvar height_half = height / 2;\r\n\r\n\t\tvar gridX = Math.floor( widthSegments ) || 1;\r\n\t\tvar gridY = Math.floor( heightSegments ) || 1;\r\n\r\n\t\tvar gridX1 = gridX + 1;\r\n\t\tvar gridY1 = gridY + 1;\r\n\r\n\t\tvar segment_width = width / gridX;\r\n\t\tvar segment_height = height / gridY;\r\n\r\n\t\tvar ix, iy;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( iy = 0; iy < gridY1; iy ++ ) {\r\n\r\n\t\t\tvar y = iy * segment_height - height_half;\r\n\r\n\t\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\r\n\r\n\t\t\t\tvar x = ix * segment_width - width_half;\r\n\r\n\t\t\t\tvertices.push( x, - y, 0 );\r\n\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t\tuvs.push( ix / gridX );\r\n\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( iy = 0; iy < gridY; iy ++ ) {\r\n\r\n\t\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\r\n\r\n\t\t\t\tvar a = ix + gridX1 * iy;\r\n\t\t\t\tvar b = ix + gridX1 * ( iy + 1 );\r\n\t\t\t\tvar c = ( ix + 1 ) + gridX1 * ( iy + 1 );\r\n\t\t\t\tvar d = ( ix + 1 ) + gridX1 * iy;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tPlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tPlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLBackground( renderer, state, objects, premultipliedAlpha ) {\r\n\r\n\t\tvar clearColor = new Color( 0x000000 );\r\n\t\tvar clearAlpha = 0;\r\n\r\n\t\tvar planeMesh;\r\n\t\tvar boxMesh;\r\n\t\t// Store the current background texture and its `version`\r\n\t\t// so we can recompile the material accordingly.\r\n\t\tvar currentBackground = null;\r\n\t\tvar currentBackgroundVersion = 0;\r\n\r\n\t\tfunction render( renderList, scene, camera, forceClear ) {\r\n\r\n\t\t\tvar background = scene.background;\r\n\r\n\t\t\t// Ignore background in AR\r\n\t\t\t// TODO: Reconsider this.\r\n\r\n\t\t\tvar xr = renderer.xr;\r\n\t\t\tvar session = xr.getSession && xr.getSession();\r\n\r\n\t\t\tif ( session && session.environmentBlendMode === 'additive' ) {\r\n\r\n\t\t\t\tbackground = null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( background === null ) {\r\n\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\t\t\t\tcurrentBackground = null;\r\n\t\t\t\tcurrentBackgroundVersion = 0;\r\n\r\n\t\t\t} else if ( background && background.isColor ) {\r\n\r\n\t\t\t\tsetClear( background, 1 );\r\n\t\t\t\tforceClear = true;\r\n\t\t\t\tcurrentBackground = null;\r\n\t\t\t\tcurrentBackgroundVersion = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderer.autoClear || forceClear ) {\r\n\r\n\t\t\t\trenderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( background && ( background.isCubeTexture || background.isWebGLRenderTargetCube || background.mapping === CubeUVReflectionMapping ) ) {\r\n\r\n\t\t\t\tif ( boxMesh === undefined ) {\r\n\r\n\t\t\t\t\tboxMesh = new Mesh(\r\n\t\t\t\t\t\tnew BoxBufferGeometry( 1, 1, 1 ),\r\n\t\t\t\t\t\tnew ShaderMaterial( {\r\n\t\t\t\t\t\t\ttype: 'BackgroundCubeMaterial',\r\n\t\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.cube.uniforms ),\r\n\t\t\t\t\t\t\tvertexShader: ShaderLib.cube.vertexShader,\r\n\t\t\t\t\t\t\tfragmentShader: ShaderLib.cube.fragmentShader,\r\n\t\t\t\t\t\t\tside: BackSide,\r\n\t\t\t\t\t\t\tdepthTest: false,\r\n\t\t\t\t\t\t\tdepthWrite: false,\r\n\t\t\t\t\t\t\tfog: false\r\n\t\t\t\t\t\t} )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tboxMesh.geometry.deleteAttribute( 'normal' );\r\n\t\t\t\t\tboxMesh.geometry.deleteAttribute( 'uv' );\r\n\r\n\t\t\t\t\tboxMesh.onBeforeRender = function ( renderer, scene, camera ) {\r\n\r\n\t\t\t\t\t\tthis.matrixWorld.copyPosition( camera.matrixWorld );\r\n\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t\t// enable code injection for non-built-in material\r\n\t\t\t\t\tObject.defineProperty( boxMesh.material, 'map', {\r\n\r\n\t\t\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\t\t\treturn this.envMap.value;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\tobjects.update( boxMesh );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar texture = background.isWebGLRenderTargetCube ? background.texture : background;\r\n\t\t\t\tboxMesh.material.envMap = texture;\r\n\r\n\t\t\t\tif ( currentBackground !== background ||\r\n\t\t\t\t currentBackgroundVersion !== texture.version ) {\r\n\r\n\t\t\t\t\tboxMesh.material.needsUpdate = true;\r\n\r\n\t\t\t\t\tcurrentBackground = background;\r\n\t\t\t\t\tcurrentBackgroundVersion = texture.version;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// push to the pre-sorted opaque render list\r\n\t\t\t\trenderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );\r\n\r\n\t\t\t} else if ( background && background.isTexture ) {\r\n\r\n\t\t\t\tif ( planeMesh === undefined ) {\r\n\r\n\t\t\t\t\tplaneMesh = new Mesh(\r\n\t\t\t\t\t\tnew PlaneBufferGeometry( 2, 2 ),\r\n\t\t\t\t\t\tnew ShaderMaterial( {\r\n\t\t\t\t\t\t\ttype: 'BackgroundMaterial',\r\n\t\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.background.uniforms ),\r\n\t\t\t\t\t\t\tvertexShader: ShaderLib.background.vertexShader,\r\n\t\t\t\t\t\t\tfragmentShader: ShaderLib.background.fragmentShader,\r\n\t\t\t\t\t\t\tside: FrontSide,\r\n\t\t\t\t\t\t\tdepthTest: false,\r\n\t\t\t\t\t\t\tdepthWrite: false,\r\n\t\t\t\t\t\t\tfog: false\r\n\t\t\t\t\t\t} )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tplaneMesh.geometry.deleteAttribute( 'normal' );\r\n\r\n\t\t\t\t\t// enable code injection for non-built-in material\r\n\t\t\t\t\tObject.defineProperty( planeMesh.material, 'map', {\r\n\r\n\t\t\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\t\t\treturn this.uniforms.t2D.value;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\tobjects.update( planeMesh );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tplaneMesh.material.uniforms.t2D.value = background;\r\n\r\n\t\t\t\tif ( background.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tbackground.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tplaneMesh.material.uniforms.uvTransform.value.copy( background.matrix );\r\n\r\n\t\t\t\tif ( currentBackground !== background ||\r\n\t\t\t\t\t currentBackgroundVersion !== background.version ) {\r\n\r\n\t\t\t\t\tplaneMesh.material.needsUpdate = true;\r\n\r\n\t\t\t\t\tcurrentBackground = background;\r\n\t\t\t\t\tcurrentBackgroundVersion = background.version;\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t// push to the pre-sorted opaque render list\r\n\t\t\t\trenderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setClear( color, alpha ) {\r\n\r\n\t\t\tstate.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tgetClearColor: function () {\r\n\r\n\t\t\t\treturn clearColor;\r\n\r\n\t\t\t},\r\n\t\t\tsetClearColor: function ( color, alpha ) {\r\n\r\n\t\t\t\tclearColor.set( color );\r\n\t\t\t\tclearAlpha = alpha !== undefined ? alpha : 1;\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\r\n\t\t\t},\r\n\t\t\tgetClearAlpha: function () {\r\n\r\n\t\t\t\treturn clearAlpha;\r\n\r\n\t\t\t},\r\n\t\t\tsetClearAlpha: function ( alpha ) {\r\n\r\n\t\t\t\tclearAlpha = alpha;\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\r\n\t\t\t},\r\n\t\t\trender: render\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLBufferRenderer( gl, extensions, info, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tvar mode;\r\n\r\n\t\tfunction setMode( value ) {\r\n\r\n\t\t\tmode = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction render( start, count ) {\r\n\r\n\t\t\tgl.drawArrays( mode, start, count );\r\n\r\n\t\t\tinfo.update( count, mode );\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderInstances( geometry, start, count, primcount ) {\r\n\r\n\t\t\tif ( primcount === 0 ) { return; }\r\n\r\n\t\t\tvar extension, methodName;\r\n\r\n\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\textension = gl;\r\n\t\t\t\tmethodName = 'drawArraysInstanced';\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\r\n\t\t\t\tmethodName = 'drawArraysInstancedANGLE';\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\textension[ methodName ]( mode, start, count, primcount );\r\n\r\n\t\t\tinfo.update( count, mode, primcount );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.setMode = setMode;\r\n\t\tthis.render = render;\r\n\t\tthis.renderInstances = renderInstances;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLCapabilities( gl, extensions, parameters ) {\r\n\r\n\t\tvar maxAnisotropy;\r\n\r\n\t\tfunction getMaxAnisotropy() {\r\n\r\n\t\t\tif ( maxAnisotropy !== undefined ) { return maxAnisotropy; }\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\r\n\r\n\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\tmaxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmaxAnisotropy = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn maxAnisotropy;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getMaxPrecision( precision ) {\r\n\r\n\t\t\tif ( precision === 'highp' ) {\r\n\r\n\t\t\t\tif ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&\r\n\t\t\t\t\tgl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {\r\n\r\n\t\t\t\t\treturn 'highp';\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tprecision = 'mediump';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( precision === 'mediump' ) {\r\n\r\n\t\t\t\tif ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&\r\n\t\t\t\t\tgl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {\r\n\r\n\t\t\t\t\treturn 'mediump';\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 'lowp';\r\n\r\n\t\t}\r\n\r\n\t\t/* eslint-disable no-undef */\r\n\t\tvar isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||\r\n\t\t\t( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );\r\n\t\t/* eslint-enable no-undef */\r\n\r\n\t\tvar precision = parameters.precision !== undefined ? parameters.precision : 'highp';\r\n\t\tvar maxPrecision = getMaxPrecision( precision );\r\n\r\n\t\tif ( maxPrecision !== precision ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );\r\n\t\t\tprecision = maxPrecision;\r\n\r\n\t\t}\r\n\r\n\t\tvar logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;\r\n\r\n\t\tvar maxTextures = gl.getParameter( 34930 );\r\n\t\tvar maxVertexTextures = gl.getParameter( 35660 );\r\n\t\tvar maxTextureSize = gl.getParameter( 3379 );\r\n\t\tvar maxCubemapSize = gl.getParameter( 34076 );\r\n\r\n\t\tvar maxAttributes = gl.getParameter( 34921 );\r\n\t\tvar maxVertexUniforms = gl.getParameter( 36347 );\r\n\t\tvar maxVaryings = gl.getParameter( 36348 );\r\n\t\tvar maxFragmentUniforms = gl.getParameter( 36349 );\r\n\r\n\t\tvar vertexTextures = maxVertexTextures > 0;\r\n\t\tvar floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );\r\n\t\tvar floatVertexTextures = vertexTextures && floatFragmentTextures;\r\n\r\n\t\tvar maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;\r\n\r\n\t\treturn {\r\n\r\n\t\t\tisWebGL2: isWebGL2,\r\n\r\n\t\t\tgetMaxAnisotropy: getMaxAnisotropy,\r\n\t\t\tgetMaxPrecision: getMaxPrecision,\r\n\r\n\t\t\tprecision: precision,\r\n\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\r\n\r\n\t\t\tmaxTextures: maxTextures,\r\n\t\t\tmaxVertexTextures: maxVertexTextures,\r\n\t\t\tmaxTextureSize: maxTextureSize,\r\n\t\t\tmaxCubemapSize: maxCubemapSize,\r\n\r\n\t\t\tmaxAttributes: maxAttributes,\r\n\t\t\tmaxVertexUniforms: maxVertexUniforms,\r\n\t\t\tmaxVaryings: maxVaryings,\r\n\t\t\tmaxFragmentUniforms: maxFragmentUniforms,\r\n\r\n\t\t\tvertexTextures: vertexTextures,\r\n\t\t\tfloatFragmentTextures: floatFragmentTextures,\r\n\t\t\tfloatVertexTextures: floatVertexTextures,\r\n\r\n\t\t\tmaxSamples: maxSamples\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction WebGLClipping() {\r\n\r\n\t\tvar scope = this,\r\n\r\n\t\t\tglobalState = null,\r\n\t\t\tnumGlobalPlanes = 0,\r\n\t\t\tlocalClippingEnabled = false,\r\n\t\t\trenderingShadows = false,\r\n\r\n\t\t\tplane = new Plane(),\r\n\t\t\tviewNormalMatrix = new Matrix3(),\r\n\r\n\t\t\tuniform = { value: null, needsUpdate: false };\r\n\r\n\t\tthis.uniform = uniform;\r\n\t\tthis.numPlanes = 0;\r\n\t\tthis.numIntersection = 0;\r\n\r\n\t\tthis.init = function ( planes, enableLocalClipping, camera ) {\r\n\r\n\t\t\tvar enabled =\r\n\t\t\t\tplanes.length !== 0 ||\r\n\t\t\t\tenableLocalClipping ||\r\n\t\t\t\t// enable state of previous frame - the clipping code has to\r\n\t\t\t\t// run another frame in order to reset the state:\r\n\t\t\t\tnumGlobalPlanes !== 0 ||\r\n\t\t\t\tlocalClippingEnabled;\r\n\r\n\t\t\tlocalClippingEnabled = enableLocalClipping;\r\n\r\n\t\t\tglobalState = projectPlanes( planes, camera, 0 );\r\n\t\t\tnumGlobalPlanes = planes.length;\r\n\r\n\t\t\treturn enabled;\r\n\r\n\t\t};\r\n\r\n\t\tthis.beginShadows = function () {\r\n\r\n\t\t\trenderingShadows = true;\r\n\t\t\tprojectPlanes( null );\r\n\r\n\t\t};\r\n\r\n\t\tthis.endShadows = function () {\r\n\r\n\t\t\trenderingShadows = false;\r\n\t\t\tresetGlobalState();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {\r\n\r\n\t\t\tif ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {\r\n\r\n\t\t\t\t// there's no local clipping\r\n\r\n\t\t\t\tif ( renderingShadows ) {\r\n\r\n\t\t\t\t\t// there's no global clipping\r\n\r\n\t\t\t\t\tprojectPlanes( null );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tresetGlobalState();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar nGlobal = renderingShadows ? 0 : numGlobalPlanes,\r\n\t\t\t\t\tlGlobal = nGlobal * 4,\r\n\r\n\t\t\t\t\tdstArray = cache.clippingState || null;\r\n\r\n\t\t\t\tuniform.value = dstArray; // ensure unique state\r\n\r\n\t\t\t\tdstArray = projectPlanes( planes, camera, lGlobal, fromCache );\r\n\r\n\t\t\t\tfor ( var i = 0; i !== lGlobal; ++ i ) {\r\n\r\n\t\t\t\t\tdstArray[ i ] = globalState[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcache.clippingState = dstArray;\r\n\t\t\t\tthis.numIntersection = clipIntersection ? this.numPlanes : 0;\r\n\t\t\t\tthis.numPlanes += nGlobal;\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t};\r\n\r\n\t\tfunction resetGlobalState() {\r\n\r\n\t\t\tif ( uniform.value !== globalState ) {\r\n\r\n\t\t\t\tuniform.value = globalState;\r\n\t\t\t\tuniform.needsUpdate = numGlobalPlanes > 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.numPlanes = numGlobalPlanes;\r\n\t\t\tscope.numIntersection = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction projectPlanes( planes, camera, dstOffset, skipTransform ) {\r\n\r\n\t\t\tvar nPlanes = planes !== null ? planes.length : 0,\r\n\t\t\t\tdstArray = null;\r\n\r\n\t\t\tif ( nPlanes !== 0 ) {\r\n\r\n\t\t\t\tdstArray = uniform.value;\r\n\r\n\t\t\t\tif ( skipTransform !== true || dstArray === null ) {\r\n\r\n\t\t\t\t\tvar flatSize = dstOffset + nPlanes * 4,\r\n\t\t\t\t\t\tviewMatrix = camera.matrixWorldInverse;\r\n\r\n\t\t\t\t\tviewNormalMatrix.getNormalMatrix( viewMatrix );\r\n\r\n\t\t\t\t\tif ( dstArray === null || dstArray.length < flatSize ) {\r\n\r\n\t\t\t\t\t\tdstArray = new Float32Array( flatSize );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfor ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {\r\n\r\n\t\t\t\t\t\tplane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );\r\n\r\n\t\t\t\t\t\tplane.normal.toArray( dstArray, i4 );\r\n\t\t\t\t\t\tdstArray[ i4 + 3 ] = plane.constant;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniform.value = dstArray;\r\n\t\t\t\tuniform.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.numPlanes = nPlanes;\r\n\r\n\t\t\treturn dstArray;\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLExtensions( gl ) {\r\n\r\n\t\tvar extensions = {};\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: function ( name ) {\r\n\r\n\t\t\t\tif ( extensions[ name ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn extensions[ name ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar extension;\r\n\r\n\t\t\t\tswitch ( name ) {\r\n\r\n\t\t\t\t\tcase 'WEBGL_depth_texture':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'EXT_texture_filter_anisotropic':\r\n\t\t\t\t\t\textension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'WEBGL_compressed_texture_s3tc':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'WEBGL_compressed_texture_pvrtc':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\textension = gl.getExtension( name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\textensions[ name ] = extension;\r\n\r\n\t\t\t\treturn extension;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLGeometries( gl, attributes, info ) {\r\n\r\n\t\tvar geometries = new WeakMap();\r\n\t\tvar wireframeAttributes = new WeakMap();\r\n\r\n\t\tfunction onGeometryDispose( event ) {\r\n\r\n\t\t\tvar geometry = event.target;\r\n\t\t\tvar buffergeometry = geometries.get( geometry );\r\n\r\n\t\t\tif ( buffergeometry.index !== null ) {\r\n\r\n\t\t\t\tattributes.remove( buffergeometry.index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var name in buffergeometry.attributes ) {\r\n\r\n\t\t\t\tattributes.remove( buffergeometry.attributes[ name ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.removeEventListener( 'dispose', onGeometryDispose );\r\n\r\n\t\t\tgeometries.delete( geometry );\r\n\r\n\t\t\tvar attribute = wireframeAttributes.get( buffergeometry );\r\n\r\n\t\t\tif ( attribute ) {\r\n\r\n\t\t\t\tattributes.remove( attribute );\r\n\t\t\t\twireframeAttributes.delete( buffergeometry );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tinfo.memory.geometries --;\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( object, geometry ) {\r\n\r\n\t\t\tvar buffergeometry = geometries.get( geometry );\r\n\r\n\t\t\tif ( buffergeometry ) { return buffergeometry; }\r\n\r\n\t\t\tgeometry.addEventListener( 'dispose', onGeometryDispose );\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tbuffergeometry = geometry;\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tif ( geometry._bufferGeometry === undefined ) {\r\n\r\n\t\t\t\t\tgeometry._bufferGeometry = new BufferGeometry().setFromObject( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbuffergeometry = geometry._bufferGeometry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometries.set( geometry, buffergeometry );\r\n\r\n\t\t\tinfo.memory.geometries ++;\r\n\r\n\t\t\treturn buffergeometry;\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( geometry ) {\r\n\r\n\t\t\tvar index = geometry.index;\r\n\t\t\tvar geometryAttributes = geometry.attributes;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tattributes.update( index, 34963 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var name in geometryAttributes ) {\r\n\r\n\t\t\t\tattributes.update( geometryAttributes[ name ], 34962 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph targets\r\n\r\n\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\r\n\t\t\tfor ( var name in morphAttributes ) {\r\n\r\n\t\t\t\tvar array = morphAttributes[ name ];\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tattributes.update( array[ i ], 34962 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateWireframeAttribute( geometry ) {\r\n\r\n\t\t\tvar indices = [];\r\n\r\n\t\t\tvar geometryIndex = geometry.index;\r\n\t\t\tvar geometryPosition = geometry.attributes.position;\r\n\t\t\tvar version = 0;\r\n\r\n\t\t\tif ( geometryIndex !== null ) {\r\n\r\n\t\t\t\tvar array = geometryIndex.array;\r\n\t\t\t\tversion = geometryIndex.version;\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\tvar a = array[ i + 0 ];\r\n\t\t\t\t\tvar b = array[ i + 1 ];\r\n\t\t\t\t\tvar c = array[ i + 2 ];\r\n\r\n\t\t\t\t\tindices.push( a, b, b, c, c, a );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar array = geometryPosition.array;\r\n\t\t\t\tversion = geometryPosition.version;\r\n\r\n\t\t\t\tfor ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\tvar a = i + 0;\r\n\t\t\t\t\tvar b = i + 1;\r\n\t\t\t\t\tvar c = i + 2;\r\n\r\n\t\t\t\t\tindices.push( a, b, b, c, c, a );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );\r\n\t\t\tattribute.version = version;\r\n\r\n\t\t\tattributes.update( attribute, 34963 );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar previousAttribute = wireframeAttributes.get( geometry );\r\n\r\n\t\t\tif ( previousAttribute ) { attributes.remove( previousAttribute ); }\r\n\r\n\t\t\t//\r\n\r\n\t\t\twireframeAttributes.set( geometry, attribute );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getWireframeAttribute( geometry ) {\r\n\r\n\t\t\tvar currentAttribute = wireframeAttributes.get( geometry );\r\n\r\n\t\t\tif ( currentAttribute ) {\r\n\r\n\t\t\t\tvar geometryIndex = geometry.index;\r\n\r\n\t\t\t\tif ( geometryIndex !== null ) {\r\n\r\n\t\t\t\t\t// if the attribute is obsolete, create a new one\r\n\r\n\t\t\t\t\tif ( currentAttribute.version < geometryIndex.version ) {\r\n\r\n\t\t\t\t\t\tupdateWireframeAttribute( geometry );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tupdateWireframeAttribute( geometry );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn wireframeAttributes.get( geometry );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: get,\r\n\t\t\tupdate: update,\r\n\r\n\t\t\tgetWireframeAttribute: getWireframeAttribute\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tvar mode;\r\n\r\n\t\tfunction setMode( value ) {\r\n\r\n\t\t\tmode = value;\r\n\r\n\t\t}\r\n\r\n\t\tvar type, bytesPerElement;\r\n\r\n\t\tfunction setIndex( value ) {\r\n\r\n\t\t\ttype = value.type;\r\n\t\t\tbytesPerElement = value.bytesPerElement;\r\n\r\n\t\t}\r\n\r\n\t\tfunction render( start, count ) {\r\n\r\n\t\t\tgl.drawElements( mode, count, type, start * bytesPerElement );\r\n\r\n\t\t\tinfo.update( count, mode );\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderInstances( geometry, start, count, primcount ) {\r\n\r\n\t\t\tif ( primcount === 0 ) { return; }\r\n\r\n\t\t\tvar extension, methodName;\r\n\r\n\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\textension = gl;\r\n\t\t\t\tmethodName = 'drawElementsInstanced';\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\r\n\t\t\t\tmethodName = 'drawElementsInstancedANGLE';\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\textension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );\r\n\r\n\t\t\tinfo.update( count, mode, primcount );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.setMode = setMode;\r\n\t\tthis.setIndex = setIndex;\r\n\t\tthis.render = render;\r\n\t\tthis.renderInstances = renderInstances;\r\n\r\n\t}\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WebGLInfo( gl ) {\r\n\r\n\t\tvar memory = {\r\n\t\t\tgeometries: 0,\r\n\t\t\ttextures: 0\r\n\t\t};\r\n\r\n\t\tvar render = {\r\n\t\t\tframe: 0,\r\n\t\t\tcalls: 0,\r\n\t\t\ttriangles: 0,\r\n\t\t\tpoints: 0,\r\n\t\t\tlines: 0\r\n\t\t};\r\n\r\n\t\tfunction update( count, mode, instanceCount ) {\r\n\r\n\t\t\tinstanceCount = instanceCount || 1;\r\n\r\n\t\t\trender.calls ++;\r\n\r\n\t\t\tswitch ( mode ) {\r\n\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\trender.triangles += instanceCount * ( count / 3 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\trender.lines += instanceCount * ( count / 2 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\trender.lines += instanceCount * ( count - 1 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\trender.lines += instanceCount * count;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\trender.points += instanceCount * count;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction reset() {\r\n\r\n\t\t\trender.frame ++;\r\n\t\t\trender.calls = 0;\r\n\t\t\trender.triangles = 0;\r\n\t\t\trender.points = 0;\r\n\t\t\trender.lines = 0;\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tmemory: memory,\r\n\t\t\trender: render,\r\n\t\t\tprograms: null,\r\n\t\t\tautoReset: true,\r\n\t\t\treset: reset,\r\n\t\t\tupdate: update\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction absNumericalSort( a, b ) {\r\n\r\n\t\treturn Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );\r\n\r\n\t}\r\n\r\n\tfunction WebGLMorphtargets( gl ) {\r\n\r\n\t\tvar influencesList = {};\r\n\t\tvar morphInfluences = new Float32Array( 8 );\r\n\r\n\t\tfunction update( object, geometry, material, program ) {\r\n\r\n\t\t\tvar objectInfluences = object.morphTargetInfluences;\r\n\r\n\t\t\t// When object doesn't have morph target influences defined, we treat it as a 0-length array\r\n\t\t\t// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences\r\n\r\n\t\t\tvar length = objectInfluences === undefined ? 0 : objectInfluences.length;\r\n\r\n\t\t\tvar influences = influencesList[ geometry.id ];\r\n\r\n\t\t\tif ( influences === undefined ) {\r\n\r\n\t\t\t\t// initialise list\r\n\r\n\t\t\t\tinfluences = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\t\tinfluences[ i ] = [ i, 0 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tinfluencesList[ geometry.id ] = influences;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphTargets = material.morphTargets && geometry.morphAttributes.position;\r\n\t\t\tvar morphNormals = material.morphNormals && geometry.morphAttributes.normal;\r\n\r\n\t\t\t// Remove current morphAttributes\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tif ( influence[ 1 ] !== 0 ) {\r\n\r\n\t\t\t\t\tif ( morphTargets ) { geometry.deleteAttribute( 'morphTarget' + i ); }\r\n\t\t\t\t\tif ( morphNormals ) { geometry.deleteAttribute( 'morphNormal' + i ); }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Collect influences\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tinfluence[ 0 ] = i;\r\n\t\t\t\tinfluence[ 1 ] = objectInfluences[ i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tinfluences.sort( absNumericalSort );\r\n\r\n\t\t\t// Add morphAttributes\r\n\r\n\t\t\tvar morphInfluencesSum = 0;\r\n\r\n\t\t\tfor ( var i = 0; i < 8; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tif ( influence ) {\r\n\r\n\t\t\t\t\tvar index = influence[ 0 ];\r\n\t\t\t\t\tvar value = influence[ 1 ];\r\n\r\n\t\t\t\t\tif ( value ) {\r\n\r\n\t\t\t\t\t\tif ( morphTargets ) { geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] ); }\r\n\t\t\t\t\t\tif ( morphNormals ) { geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] ); }\r\n\r\n\t\t\t\t\t\tmorphInfluences[ i ] = value;\r\n\t\t\t\t\t\tmorphInfluencesSum += value;\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmorphInfluences[ i ] = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// GLSL shader uses formula baseinfluence * base + sum(target * influence)\r\n\t\t\t// This allows us to switch between absolute morphs and relative morphs without changing shader code\r\n\t\t\t// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)\r\n\t\t\tvar morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;\r\n\r\n\t\t\tprogram.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );\r\n\t\t\tprogram.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tupdate: update\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLObjects( gl, geometries, attributes, info ) {\r\n\r\n\t\tvar updateList = {};\r\n\r\n\t\tfunction update( object ) {\r\n\r\n\t\t\tvar frame = info.render.frame;\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\t\t\tvar buffergeometry = geometries.get( object, geometry );\r\n\r\n\t\t\t// Update once per frame\r\n\r\n\t\t\tif ( updateList[ buffergeometry.id ] !== frame ) {\r\n\r\n\t\t\t\tif ( geometry.isGeometry ) {\r\n\r\n\t\t\t\t\tbuffergeometry.updateFromObject( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometries.update( buffergeometry );\r\n\r\n\t\t\t\tupdateList[ buffergeometry.id ] = frame;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.isInstancedMesh ) {\r\n\r\n\t\t\t\tattributes.update( object.instanceMatrix, 34962 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn buffergeometry;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tupdateList = {};\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tupdate: update,\r\n\t\t\tdispose: dispose\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\r\n\r\n\t\timages = images !== undefined ? images : [];\r\n\t\tmapping = mapping !== undefined ? mapping : CubeReflectionMapping;\r\n\t\tformat = format !== undefined ? format : RGBFormat;\r\n\r\n\t\tTexture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.flipY = false;\r\n\r\n\t}\r\n\r\n\tCubeTexture.prototype = Object.create( Texture.prototype );\r\n\tCubeTexture.prototype.constructor = CubeTexture;\r\n\r\n\tCubeTexture.prototype.isCubeTexture = true;\r\n\r\n\tObject.defineProperty( CubeTexture.prototype, 'images', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\treturn this.image;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tthis.image = value;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction DataTexture2DArray( data, width, height, depth ) {\r\n\r\n\t\tTexture.call( this, null );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\r\n\r\n\t\tthis.magFilter = NearestFilter;\r\n\t\tthis.minFilter = NearestFilter;\r\n\r\n\t\tthis.wrapR = ClampToEdgeWrapping;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tDataTexture2DArray.prototype = Object.create( Texture.prototype );\r\n\tDataTexture2DArray.prototype.constructor = DataTexture2DArray;\r\n\tDataTexture2DArray.prototype.isDataTexture2DArray = true;\n\n\t/**\r\n\t * @author Artur Trzesiok\r\n\t */\r\n\r\n\tfunction DataTexture3D( data, width, height, depth ) {\r\n\r\n\t\t// We're going to add .setXXX() methods for setting properties later.\r\n\t\t// Users can still set in DataTexture3D directly.\r\n\t\t//\r\n\t\t//\tvar texture = new THREE.DataTexture3D( data, width, height, depth );\r\n\t\t// \ttexture.anisotropy = 16;\r\n\t\t//\r\n\t\t// See #14839\r\n\r\n\t\tTexture.call( this, null );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\r\n\r\n\t\tthis.magFilter = NearestFilter;\r\n\t\tthis.minFilter = NearestFilter;\r\n\r\n\t\tthis.wrapR = ClampToEdgeWrapping;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\r\n\t}\r\n\r\n\tDataTexture3D.prototype = Object.create( Texture.prototype );\r\n\tDataTexture3D.prototype.constructor = DataTexture3D;\r\n\tDataTexture3D.prototype.isDataTexture3D = true;\n\n\t/**\r\n\t * @author tschw\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * Uniforms of a program.\r\n\t * Those form a tree structure with a special top-level container for the root,\r\n\t * which you get by calling 'new WebGLUniforms( gl, program )'.\r\n\t *\r\n\t *\r\n\t * Properties of inner nodes including the top-level container:\r\n\t *\r\n\t * .seq - array of nested uniforms\r\n\t * .map - nested uniforms by name\r\n\t *\r\n\t *\r\n\t * Methods of all nodes except the top-level container:\r\n\t *\r\n\t * .setValue( gl, value, [textures] )\r\n\t *\r\n\t * \t\tuploads a uniform value(s)\r\n\t * \tthe 'textures' parameter is needed for sampler uniforms\r\n\t *\r\n\t *\r\n\t * Static methods of the top-level container (textures factorizations):\r\n\t *\r\n\t * .upload( gl, seq, values, textures )\r\n\t *\r\n\t * \t\tsets uniforms in 'seq' to 'values[id].value'\r\n\t *\r\n\t * .seqWithValue( seq, values ) : filteredSeq\r\n\t *\r\n\t * \t\tfilters 'seq' entries with corresponding entry in values\r\n\t *\r\n\t *\r\n\t * Methods of the top-level container (textures factorizations):\r\n\t *\r\n\t * .setValue( gl, name, value, textures )\r\n\t *\r\n\t * \t\tsets uniform with name 'name' to 'value'\r\n\t *\r\n\t * .setOptional( gl, obj, prop )\r\n\t *\r\n\t * \t\tlike .set for an optional property of the object\r\n\t *\r\n\t */\r\n\r\n\tvar emptyTexture = new Texture();\r\n\tvar emptyTexture2dArray = new DataTexture2DArray();\r\n\tvar emptyTexture3d = new DataTexture3D();\r\n\tvar emptyCubeTexture = new CubeTexture();\r\n\r\n\t// --- Utilities ---\r\n\r\n\t// Array Caches (provide typed arrays for temporary by size)\r\n\r\n\tvar arrayCacheF32 = [];\r\n\tvar arrayCacheI32 = [];\r\n\r\n\t// Float32Array caches used for uploading Matrix uniforms\r\n\r\n\tvar mat4array = new Float32Array( 16 );\r\n\tvar mat3array = new Float32Array( 9 );\r\n\tvar mat2array = new Float32Array( 4 );\r\n\r\n\t// Flattening for arrays of vectors and matrices\r\n\r\n\tfunction flatten( array, nBlocks, blockSize ) {\r\n\r\n\t\tvar firstElem = array[ 0 ];\r\n\r\n\t\tif ( firstElem <= 0 || firstElem > 0 ) { return array; }\r\n\t\t// unoptimized: ! isNaN( firstElem )\r\n\t\t// see http://jacksondunstan.com/articles/983\r\n\r\n\t\tvar n = nBlocks * blockSize,\r\n\t\t\tr = arrayCacheF32[ n ];\r\n\r\n\t\tif ( r === undefined ) {\r\n\r\n\t\t\tr = new Float32Array( n );\r\n\t\t\tarrayCacheF32[ n ] = r;\r\n\r\n\t\t}\r\n\r\n\t\tif ( nBlocks !== 0 ) {\r\n\r\n\t\t\tfirstElem.toArray( r, 0 );\r\n\r\n\t\t\tfor ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {\r\n\r\n\t\t\t\toffset += blockSize;\r\n\t\t\t\tarray[ i ].toArray( r, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn r;\r\n\r\n\t}\r\n\r\n\tfunction arraysEqual( a, b ) {\r\n\r\n\t\tif ( a.length !== b.length ) { return false; }\r\n\r\n\t\tfor ( var i = 0, l = a.length; i < l; i ++ ) {\r\n\r\n\t\t\tif ( a[ i ] !== b[ i ] ) { return false; }\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\tfunction copyArray( a, b ) {\r\n\r\n\t\tfor ( var i = 0, l = b.length; i < l; i ++ ) {\r\n\r\n\t\t\ta[ i ] = b[ i ];\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Texture unit allocation\r\n\r\n\tfunction allocTexUnits( textures, n ) {\r\n\r\n\t\tvar r = arrayCacheI32[ n ];\r\n\r\n\t\tif ( r === undefined ) {\r\n\r\n\t\t\tr = new Int32Array( n );\r\n\t\t\tarrayCacheI32[ n ] = r;\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i )\r\n\t\t\t{ r[ i ] = textures.allocateTextureUnit(); }\r\n\r\n\t\treturn r;\r\n\r\n\t}\r\n\r\n\t// --- Setters ---\r\n\r\n\t// Note: Defining these methods externally, because they come in a bunch\r\n\t// and this way their names minify.\r\n\r\n\t// Single scalar\r\n\r\n\tfunction setValueV1f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( cache[ 0 ] === v ) { return; }\r\n\r\n\t\tgl.uniform1f( this.addr, v );\r\n\r\n\t\tcache[ 0 ] = v;\r\n\r\n\t}\r\n\r\n\t// Single float vector (from flat array or THREE.VectorN)\r\n\r\n\tfunction setValueV2f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {\r\n\r\n\t\t\t\tgl.uniform2f( this.addr, v.x, v.y );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform2fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueV3f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {\r\n\r\n\t\t\t\tgl.uniform3f( this.addr, v.x, v.y, v.z );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\t\t\t\tcache[ 2 ] = v.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( v.r !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {\r\n\r\n\t\t\t\tgl.uniform3f( this.addr, v.r, v.g, v.b );\r\n\r\n\t\t\t\tcache[ 0 ] = v.r;\r\n\t\t\t\tcache[ 1 ] = v.g;\r\n\t\t\t\tcache[ 2 ] = v.b;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform3fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueV4f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {\r\n\r\n\t\t\t\tgl.uniform4f( this.addr, v.x, v.y, v.z, v.w );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\t\t\t\tcache[ 2 ] = v.z;\r\n\t\t\t\tcache[ 3 ] = v.w;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform4fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Single matrix (from flat array or MatrixN)\r\n\r\n\tfunction setValueM2( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix2fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat2array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix2fv( this.addr, false, mat2array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueM3( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix3fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat3array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix3fv( this.addr, false, mat3array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueM4( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix4fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat4array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix4fv( this.addr, false, mat4array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Single texture (2D / Cube)\r\n\r\n\tfunction setValueT1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.safeSetTexture2D( v || emptyTexture, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT2DArray1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.setTexture2DArray( v || emptyTexture2dArray, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT3D1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.setTexture3D( v || emptyTexture3d, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT6( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.safeSetTextureCube( v || emptyCubeTexture, unit );\r\n\r\n\t}\r\n\r\n\t// Integer / Boolean vectors or arrays thereof (always flat arrays)\r\n\r\n\tfunction setValueV1i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( cache[ 0 ] === v ) { return; }\r\n\r\n\t\tgl.uniform1i( this.addr, v );\r\n\r\n\t\tcache[ 0 ] = v;\r\n\r\n\t}\r\n\r\n\tfunction setValueV2i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform2iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform3iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform4iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\t// Helper to pick the right setter for the singular case\r\n\r\n\tfunction getSingularSetter( type ) {\r\n\r\n\t\tswitch ( type ) {\r\n\r\n\t\t\tcase 0x1406: return setValueV1f; // FLOAT\r\n\t\t\tcase 0x8b50: return setValueV2f; // _VEC2\r\n\t\t\tcase 0x8b51: return setValueV3f; // _VEC3\r\n\t\t\tcase 0x8b52: return setValueV4f; // _VEC4\r\n\r\n\t\t\tcase 0x8b5a: return setValueM2; // _MAT2\r\n\t\t\tcase 0x8b5b: return setValueM3; // _MAT3\r\n\t\t\tcase 0x8b5c: return setValueM4; // _MAT4\r\n\r\n\t\t\tcase 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES\r\n\t\t\tcase 0x8b5f: return setValueT3D1; // SAMPLER_3D\r\n\t\t\tcase 0x8b60: return setValueT6; // SAMPLER_CUBE\r\n\t\t\tcase 0x8DC1: return setValueT2DArray1; // SAMPLER_2D_ARRAY\r\n\r\n\t\t\tcase 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL\r\n\t\t\tcase 0x8b53: case 0x8b57: return setValueV2i; // _VEC2\r\n\t\t\tcase 0x8b54: case 0x8b58: return setValueV3i; // _VEC3\r\n\t\t\tcase 0x8b55: case 0x8b59: return setValueV4i; // _VEC4\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Array of scalars\r\n\tfunction setValueV1fArray( gl, v ) {\r\n\r\n\t\tgl.uniform1fv( this.addr, v );\r\n\r\n\t}\r\n\r\n\t// Integer / Boolean vectors or arrays thereof (always flat arrays)\r\n\tfunction setValueV1iArray( gl, v ) {\r\n\r\n\t\tgl.uniform1iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV2iArray( gl, v ) {\r\n\r\n\t\tgl.uniform2iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3iArray( gl, v ) {\r\n\r\n\t\tgl.uniform3iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4iArray( gl, v ) {\r\n\r\n\t\tgl.uniform4iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\r\n\t// Array of vectors (flat or from THREE classes)\r\n\r\n\tfunction setValueV2fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 2 );\r\n\r\n\t\tgl.uniform2fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 3 );\r\n\r\n\t\tgl.uniform3fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 4 );\r\n\r\n\t\tgl.uniform4fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\t// Array of matrices (flat or from THREE clases)\r\n\r\n\tfunction setValueM2Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 4 );\r\n\r\n\t\tgl.uniformMatrix2fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueM3Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 9 );\r\n\r\n\t\tgl.uniformMatrix3fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueM4Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 16 );\r\n\r\n\t\tgl.uniformMatrix4fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\t// Array of textures (2D / Cube)\r\n\r\n\tfunction setValueT1Array( gl, v, textures ) {\r\n\r\n\t\tvar n = v.length;\r\n\r\n\t\tvar units = allocTexUnits( textures, n );\r\n\r\n\t\tgl.uniform1iv( this.addr, units );\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i ) {\r\n\r\n\t\t\ttextures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueT6Array( gl, v, textures ) {\r\n\r\n\t\tvar n = v.length;\r\n\r\n\t\tvar units = allocTexUnits( textures, n );\r\n\r\n\t\tgl.uniform1iv( this.addr, units );\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i ) {\r\n\r\n\t\t\ttextures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Helper to pick the right setter for a pure (bottom-level) array\r\n\r\n\tfunction getPureArraySetter( type ) {\r\n\r\n\t\tswitch ( type ) {\r\n\r\n\t\t\tcase 0x1406: return setValueV1fArray; // FLOAT\r\n\t\t\tcase 0x8b50: return setValueV2fArray; // _VEC2\r\n\t\t\tcase 0x8b51: return setValueV3fArray; // _VEC3\r\n\t\t\tcase 0x8b52: return setValueV4fArray; // _VEC4\r\n\r\n\t\t\tcase 0x8b5a: return setValueM2Array; // _MAT2\r\n\t\t\tcase 0x8b5b: return setValueM3Array; // _MAT3\r\n\t\t\tcase 0x8b5c: return setValueM4Array; // _MAT4\r\n\r\n\t\t\tcase 0x8b5e: return setValueT1Array; // SAMPLER_2D\r\n\t\t\tcase 0x8b60: return setValueT6Array; // SAMPLER_CUBE\r\n\r\n\t\t\tcase 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL\r\n\t\t\tcase 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2\r\n\t\t\tcase 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3\r\n\t\t\tcase 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// --- Uniform Classes ---\r\n\r\n\tfunction SingleUniform( id, activeInfo, addr ) {\r\n\r\n\t\tthis.id = id;\r\n\t\tthis.addr = addr;\r\n\t\tthis.cache = [];\r\n\t\tthis.setValue = getSingularSetter( activeInfo.type );\r\n\r\n\t\t// this.path = activeInfo.name; // DEBUG\r\n\r\n\t}\r\n\r\n\tfunction PureArrayUniform( id, activeInfo, addr ) {\r\n\r\n\t\tthis.id = id;\r\n\t\tthis.addr = addr;\r\n\t\tthis.cache = [];\r\n\t\tthis.size = activeInfo.size;\r\n\t\tthis.setValue = getPureArraySetter( activeInfo.type );\r\n\r\n\t\t// this.path = activeInfo.name; // DEBUG\r\n\r\n\t}\r\n\r\n\tPureArrayUniform.prototype.updateCache = function ( data ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( data instanceof Float32Array && cache.length !== data.length ) {\r\n\r\n\t\t\tthis.cache = new Float32Array( data.length );\r\n\r\n\t\t}\r\n\r\n\t\tcopyArray( cache, data );\r\n\r\n\t};\r\n\r\n\tfunction StructuredUniform( id ) {\r\n\r\n\t\tthis.id = id;\r\n\r\n\t\tthis.seq = [];\r\n\t\tthis.map = {};\r\n\r\n\t}\r\n\r\n\tStructuredUniform.prototype.setValue = function ( gl, value, textures ) {\r\n\r\n\t\tvar seq = this.seq;\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ];\r\n\t\t\tu.setValue( gl, value[ u.id ], textures );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t// --- Top-level ---\r\n\r\n\t// Parser - builds up the property tree from the path strings\r\n\r\n\tvar RePathPart = /([\\w\\d_]+)(\\])?(\\[|\\.)?/g;\r\n\r\n\t// extracts\r\n\t// \t- the identifier (member name or array index)\r\n\t// - followed by an optional right bracket (found when array index)\r\n\t// - followed by an optional left bracket or dot (type of subscript)\r\n\t//\r\n\t// Note: These portions can be read in a non-overlapping fashion and\r\n\t// allow straightforward parsing of the hierarchy that WebGL encodes\r\n\t// in the uniform names.\r\n\r\n\tfunction addUniform( container, uniformObject ) {\r\n\r\n\t\tcontainer.seq.push( uniformObject );\r\n\t\tcontainer.map[ uniformObject.id ] = uniformObject;\r\n\r\n\t}\r\n\r\n\tfunction parseUniform( activeInfo, addr, container ) {\r\n\r\n\t\tvar path = activeInfo.name,\r\n\t\t\tpathLength = path.length;\r\n\r\n\t\t// reset RegExp object, because of the early exit of a previous run\r\n\t\tRePathPart.lastIndex = 0;\r\n\r\n\t\twhile ( true ) {\r\n\r\n\t\t\tvar match = RePathPart.exec( path ),\r\n\t\t\t\tmatchEnd = RePathPart.lastIndex,\r\n\r\n\t\t\t\tid = match[ 1 ],\r\n\t\t\t\tidIsIndex = match[ 2 ] === ']',\r\n\t\t\t\tsubscript = match[ 3 ];\r\n\r\n\t\t\tif ( idIsIndex ) { id = id | 0; } // convert to integer\r\n\r\n\t\t\tif ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {\r\n\r\n\t\t\t\t// bare name or \"pure\" bottom-level array \"[0]\" suffix\r\n\r\n\t\t\t\taddUniform( container, subscript === undefined ?\r\n\t\t\t\t\tnew SingleUniform( id, activeInfo, addr ) :\r\n\t\t\t\t\tnew PureArrayUniform( id, activeInfo, addr ) );\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// step into inner node / create it in case it doesn't exist\r\n\r\n\t\t\t\tvar map = container.map, next = map[ id ];\r\n\r\n\t\t\t\tif ( next === undefined ) {\r\n\r\n\t\t\t\t\tnext = new StructuredUniform( id );\r\n\t\t\t\t\taddUniform( container, next );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcontainer = next;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Root Container\r\n\r\n\tfunction WebGLUniforms( gl, program ) {\r\n\r\n\t\tthis.seq = [];\r\n\t\tthis.map = {};\r\n\r\n\t\tvar n = gl.getProgramParameter( program, 35718 );\r\n\r\n\t\tfor ( var i = 0; i < n; ++ i ) {\r\n\r\n\t\t\tvar info = gl.getActiveUniform( program, i ),\r\n\t\t\t\taddr = gl.getUniformLocation( program, info.name );\r\n\r\n\t\t\tparseUniform( info, addr, this );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tWebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {\r\n\r\n\t\tvar u = this.map[ name ];\r\n\r\n\t\tif ( u !== undefined ) { u.setValue( gl, value, textures ); }\r\n\r\n\t};\r\n\r\n\tWebGLUniforms.prototype.setOptional = function ( gl, object, name ) {\r\n\r\n\t\tvar v = object[ name ];\r\n\r\n\t\tif ( v !== undefined ) { this.setValue( gl, name, v ); }\r\n\r\n\t};\r\n\r\n\r\n\t// Static interface\r\n\r\n\tWebGLUniforms.upload = function ( gl, seq, values, textures ) {\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ],\r\n\t\t\t\tv = values[ u.id ];\r\n\r\n\t\t\tif ( v.needsUpdate !== false ) {\r\n\r\n\t\t\t\t// note: always updating when .needsUpdate is undefined\r\n\t\t\t\tu.setValue( gl, v.value, textures );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tWebGLUniforms.seqWithValue = function ( seq, values ) {\r\n\r\n\t\tvar r = [];\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ];\r\n\t\t\tif ( u.id in values ) { r.push( u ); }\r\n\r\n\t\t}\r\n\r\n\t\treturn r;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLShader( gl, type, string ) {\r\n\r\n\t\tvar shader = gl.createShader( type );\r\n\r\n\t\tgl.shaderSource( shader, string );\r\n\t\tgl.compileShader( shader );\r\n\r\n\t\treturn shader;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar programIdCount = 0;\r\n\r\n\tfunction addLineNumbers( string ) {\r\n\r\n\t\tvar lines = string.split( '\\n' );\r\n\r\n\t\tfor ( var i = 0; i < lines.length; i ++ ) {\r\n\r\n\t\t\tlines[ i ] = ( i + 1 ) + ': ' + lines[ i ];\r\n\r\n\t\t}\r\n\r\n\t\treturn lines.join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction getEncodingComponents( encoding ) {\r\n\r\n\t\tswitch ( encoding ) {\r\n\r\n\t\t\tcase LinearEncoding:\r\n\t\t\t\treturn [ 'Linear', '( value )' ];\r\n\t\t\tcase sRGBEncoding:\r\n\t\t\t\treturn [ 'sRGB', '( value )' ];\r\n\t\t\tcase RGBEEncoding:\r\n\t\t\t\treturn [ 'RGBE', '( value )' ];\r\n\t\t\tcase RGBM7Encoding:\r\n\t\t\t\treturn [ 'RGBM', '( value, 7.0 )' ];\r\n\t\t\tcase RGBM16Encoding:\r\n\t\t\t\treturn [ 'RGBM', '( value, 16.0 )' ];\r\n\t\t\tcase RGBDEncoding:\r\n\t\t\t\treturn [ 'RGBD', '( value, 256.0 )' ];\r\n\t\t\tcase GammaEncoding:\r\n\t\t\t\treturn [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];\r\n\t\t\tcase LogLuvEncoding:\r\n\t\t\t\treturn [ 'LogLuv', '( value )' ];\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'unsupported encoding: ' + encoding );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction getShaderErrors( gl, shader, type ) {\r\n\r\n\t\tvar status = gl.getShaderParameter( shader, 35713 );\r\n\t\tvar log = gl.getShaderInfoLog( shader ).trim();\r\n\r\n\t\tif ( status && log === '' ) { return ''; }\r\n\r\n\t\t// --enable-privileged-webgl-extension\r\n\t\t// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );\r\n\r\n\t\tvar source = gl.getShaderSource( shader );\r\n\r\n\t\treturn 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\\n' + log + addLineNumbers( source );\r\n\r\n\t}\r\n\r\n\tfunction getTexelDecodingFunction( functionName, encoding ) {\r\n\r\n\t\tvar components = getEncodingComponents( encoding );\r\n\t\treturn 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';\r\n\r\n\t}\r\n\r\n\tfunction getTexelEncodingFunction( functionName, encoding ) {\r\n\r\n\t\tvar components = getEncodingComponents( encoding );\r\n\t\treturn 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';\r\n\r\n\t}\r\n\r\n\tfunction getToneMappingFunction( functionName, toneMapping ) {\r\n\r\n\t\tvar toneMappingName;\r\n\r\n\t\tswitch ( toneMapping ) {\r\n\r\n\t\t\tcase LinearToneMapping:\r\n\t\t\t\ttoneMappingName = 'Linear';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ReinhardToneMapping:\r\n\t\t\t\ttoneMappingName = 'Reinhard';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Uncharted2ToneMapping:\r\n\t\t\t\ttoneMappingName = 'Uncharted2';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase CineonToneMapping:\r\n\t\t\t\ttoneMappingName = 'OptimizedCineon';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ACESFilmicToneMapping:\r\n\t\t\t\ttoneMappingName = 'ACESFilmic';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'unsupported toneMapping: ' + toneMapping );\r\n\r\n\t\t}\r\n\r\n\t\treturn 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';\r\n\r\n\t}\r\n\r\n\tfunction generateExtensions( extensions, parameters, rendererExtensions ) {\r\n\r\n\t\textensions = extensions || {};\r\n\r\n\t\tvar chunks = [\r\n\t\t\t( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',\r\n\t\t\t( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',\r\n\t\t\t( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',\r\n\t\t\t( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''\r\n\t\t];\r\n\r\n\t\treturn chunks.filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction generateDefines( defines ) {\r\n\r\n\t\tvar chunks = [];\r\n\r\n\t\tfor ( var name in defines ) {\r\n\r\n\t\t\tvar value = defines[ name ];\r\n\r\n\t\t\tif ( value === false ) { continue; }\r\n\r\n\t\t\tchunks.push( '#define ' + name + ' ' + value );\r\n\r\n\t\t}\r\n\r\n\t\treturn chunks.join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction fetchAttributeLocations( gl, program ) {\r\n\r\n\t\tvar attributes = {};\r\n\r\n\t\tvar n = gl.getProgramParameter( program, 35721 );\r\n\r\n\t\tfor ( var i = 0; i < n; i ++ ) {\r\n\r\n\t\t\tvar info = gl.getActiveAttrib( program, i );\r\n\t\t\tvar name = info.name;\r\n\r\n\t\t\t// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );\r\n\r\n\t\t\tattributes[ name ] = gl.getAttribLocation( program, name );\r\n\r\n\t\t}\r\n\r\n\t\treturn attributes;\r\n\r\n\t}\r\n\r\n\tfunction filterEmptyLine( string ) {\r\n\r\n\t\treturn string !== '';\r\n\r\n\t}\r\n\r\n\tfunction replaceLightNums( string, parameters ) {\r\n\r\n\t\treturn string\r\n\t\t\t.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )\r\n\t\t\t.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )\r\n\t\t\t.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )\r\n\t\t\t.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )\r\n\t\t\t.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )\r\n\t\t\t.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )\r\n\t\t\t.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )\r\n\t\t\t.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );\r\n\r\n\t}\r\n\r\n\tfunction replaceClippingPlaneNums( string, parameters ) {\r\n\r\n\t\treturn string\r\n\t\t\t.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )\r\n\t\t\t.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );\r\n\r\n\t}\r\n\r\n\t// Resolve Includes\r\n\r\n\tvar includePattern = /^[ \\t]*#include +<([\\w\\d./]+)>/gm;\r\n\r\n\tfunction resolveIncludes( string ) {\r\n\r\n\t\treturn string.replace( includePattern, includeReplacer );\r\n\r\n\t}\r\n\r\n\tfunction includeReplacer( match, include ) {\r\n\r\n\t\tvar string = ShaderChunk[ include ];\r\n\r\n\t\tif ( string === undefined ) {\r\n\r\n\t\t\tthrow new Error( 'Can not resolve #include <' + include + '>' );\r\n\r\n\t\t}\r\n\r\n\t\treturn resolveIncludes( string );\r\n\r\n\t}\r\n\r\n\t// Unroll Loops\r\n\r\n\tvar loopPattern = /#pragma unroll_loop[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}/g;\r\n\r\n\tfunction unrollLoops( string ) {\r\n\r\n\t\treturn string.replace( loopPattern, loopReplacer );\r\n\r\n\t}\r\n\r\n\tfunction loopReplacer( match, start, end, snippet ) {\r\n\r\n\t\tvar string = '';\r\n\r\n\t\tfor ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {\r\n\r\n\t\t\tstring += snippet\r\n\t\t\t\t.replace( /\\[ i \\]/g, '[ ' + i + ' ]' )\r\n\t\t\t\t.replace( /UNROLLED_LOOP_INDEX/g, i );\r\n\r\n\t\t}\r\n\r\n\t\treturn string;\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction generatePrecision( parameters ) {\r\n\r\n\t\tvar precisionstring = \"precision \" + parameters.precision + \" float;\\nprecision \" + parameters.precision + \" int;\";\r\n\r\n\t\tif ( parameters.precision === \"highp\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define HIGH_PRECISION\";\r\n\r\n\t\t} else if ( parameters.precision === \"mediump\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define MEDIUM_PRECISION\";\r\n\r\n\t\t} else if ( parameters.precision === \"lowp\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define LOW_PRECISION\";\r\n\r\n\t\t}\r\n\r\n\t\treturn precisionstring;\r\n\r\n\t}\r\n\r\n\tfunction generateShadowMapTypeDefine( parameters ) {\r\n\r\n\t\tvar shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';\r\n\r\n\t\tif ( parameters.shadowMapType === PCFShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';\r\n\r\n\t\t} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';\r\n\r\n\t\t} else if ( parameters.shadowMapType === VSMShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';\r\n\r\n\t\t}\r\n\r\n\t\treturn shadowMapTypeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapTypeDefine( parameters ) {\r\n\r\n\t\tvar envMapTypeDefine = 'ENVMAP_TYPE_CUBE';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.envMapMode ) {\r\n\r\n\t\t\t\tcase CubeReflectionMapping:\r\n\t\t\t\tcase CubeRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase CubeUVReflectionMapping:\r\n\t\t\t\tcase CubeUVRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase EquirectangularReflectionMapping:\r\n\t\t\t\tcase EquirectangularRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase SphericalReflectionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_SPHERE';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapTypeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapModeDefine( parameters ) {\r\n\r\n\t\tvar envMapModeDefine = 'ENVMAP_MODE_REFLECTION';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.envMapMode ) {\r\n\r\n\t\t\t\tcase CubeRefractionMapping:\r\n\t\t\t\tcase EquirectangularRefractionMapping:\r\n\t\t\t\t\tenvMapModeDefine = 'ENVMAP_MODE_REFRACTION';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapModeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapBlendingDefine( parameters ) {\r\n\r\n\t\tvar envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.combine ) {\r\n\r\n\t\t\t\tcase MultiplyOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase MixOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MIX';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase AddOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_ADD';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapBlendingDefine;\r\n\r\n\t}\r\n\r\n\tfunction WebGLProgram( renderer, extensions, cacheKey, material, shader, parameters ) {\r\n\r\n\t\tvar gl = renderer.getContext();\r\n\r\n\t\tvar defines = material.defines;\r\n\r\n\t\tvar vertexShader = shader.vertexShader;\r\n\t\tvar fragmentShader = shader.fragmentShader;\r\n\t\tvar shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );\r\n\t\tvar envMapTypeDefine = generateEnvMapTypeDefine( parameters );\r\n\t\tvar envMapModeDefine = generateEnvMapModeDefine( parameters );\r\n\t\tvar envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );\r\n\r\n\r\n\t\tvar gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;\r\n\r\n\t\tvar customExtensions = parameters.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );\r\n\r\n\t\tvar customDefines = generateDefines( defines );\r\n\r\n\t\tvar program = gl.createProgram();\r\n\r\n\t\tvar prefixVertex, prefixFragment;\r\n\r\n\t\tvar numMultiviewViews = parameters.numMultiviewViews;\r\n\r\n\t\tif ( material.isRawShaderMaterial ) {\r\n\r\n\t\t\tprefixVertex = [\r\n\r\n\t\t\t\tcustomDefines\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tif ( prefixVertex.length > 0 ) {\r\n\r\n\t\t\t\tprefixVertex += '\\n';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tprefixFragment = [\r\n\r\n\t\t\t\tcustomExtensions,\r\n\t\t\t\tcustomDefines\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tif ( prefixFragment.length > 0 ) {\r\n\r\n\t\t\t\tprefixFragment += '\\n';\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tprefixVertex = [\r\n\r\n\t\t\t\tgeneratePrecision( parameters ),\r\n\r\n\t\t\t\t'#define SHADER_NAME ' + shader.name,\r\n\r\n\t\t\t\tcustomDefines,\r\n\r\n\t\t\t\tparameters.instancing ? '#define USE_INSTANCING' : '',\r\n\t\t\t\tparameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',\r\n\r\n\t\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\r\n\r\n\t\t\t\t'#define MAX_BONES ' + parameters.maxBones,\r\n\t\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\r\n\t\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\r\n\r\n\t\t\t\tparameters.map ? '#define USE_MAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\r\n\t\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\r\n\t\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\r\n\t\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\r\n\t\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\r\n\t\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\r\n\r\n\t\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\r\n\t\t\t\tparameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',\r\n\t\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\r\n\t\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\r\n\t\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\r\n\t\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\r\n\r\n\t\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\r\n\t\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\r\n\t\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\r\n\t\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\r\n\r\n\t\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\r\n\r\n\t\t\t\tparameters.skinning ? '#define USE_SKINNING' : '',\r\n\t\t\t\tparameters.useVertexTexture ? '#define BONE_TEXTURE' : '',\r\n\r\n\t\t\t\tparameters.morphTargets ? '#define USE_MORPHTARGETS' : '',\r\n\t\t\t\tparameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',\r\n\t\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\r\n\t\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\r\n\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\r\n\r\n\t\t\t\tparameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',\r\n\r\n\t\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\r\n\t\t\t\tparameters.logarithmicDepthBuffer && ( parameters.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\r\n\r\n\t\t\t\t'uniform mat4 modelMatrix;',\r\n\t\t\t\t'uniform mat4 modelViewMatrix;',\r\n\t\t\t\t'uniform mat4 projectionMatrix;',\r\n\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t'uniform mat3 normalMatrix;',\r\n\t\t\t\t'uniform vec3 cameraPosition;',\r\n\t\t\t\t'uniform bool isOrthographic;',\r\n\r\n\t\t\t\t'#ifdef USE_INSTANCING',\r\n\r\n\t\t\t\t' attribute mat4 instanceMatrix;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'attribute vec3 position;',\r\n\t\t\t\t'attribute vec3 normal;',\r\n\t\t\t\t'attribute vec2 uv;',\r\n\r\n\t\t\t\t'#ifdef USE_TANGENT',\r\n\r\n\t\t\t\t'\tattribute vec4 tangent;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_COLOR',\r\n\r\n\t\t\t\t'\tattribute vec3 color;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_MORPHTARGETS',\r\n\r\n\t\t\t\t'\tattribute vec3 morphTarget0;',\r\n\t\t\t\t'\tattribute vec3 morphTarget1;',\r\n\t\t\t\t'\tattribute vec3 morphTarget2;',\r\n\t\t\t\t'\tattribute vec3 morphTarget3;',\r\n\r\n\t\t\t\t'\t#ifdef USE_MORPHNORMALS',\r\n\r\n\t\t\t\t'\t\tattribute vec3 morphNormal0;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal1;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal2;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal3;',\r\n\r\n\t\t\t\t'\t#else',\r\n\r\n\t\t\t\t'\t\tattribute vec3 morphTarget4;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget5;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget6;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget7;',\r\n\r\n\t\t\t\t'\t#endif',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_SKINNING',\r\n\r\n\t\t\t\t'\tattribute vec4 skinIndex;',\r\n\t\t\t\t'\tattribute vec4 skinWeight;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'\\n'\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tprefixFragment = [\r\n\r\n\t\t\t\tcustomExtensions,\r\n\r\n\t\t\t\tgeneratePrecision( parameters ),\r\n\r\n\t\t\t\t'#define SHADER_NAME ' + shader.name,\r\n\r\n\t\t\t\tcustomDefines,\r\n\r\n\t\t\t\tparameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer\r\n\r\n\t\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\r\n\r\n\t\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\r\n\t\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\r\n\r\n\t\t\t\tparameters.map ? '#define USE_MAP' : '',\r\n\t\t\t\tparameters.matcap ? '#define USE_MATCAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapTypeDefine : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapBlendingDefine : '',\r\n\t\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\r\n\t\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\r\n\t\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\r\n\t\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\r\n\t\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\r\n\t\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\r\n\t\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\r\n\t\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\r\n\t\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\r\n\t\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\r\n\r\n\t\t\t\tparameters.sheen ? '#define USE_SHEEN' : '',\r\n\r\n\t\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\r\n\t\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\r\n\t\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\r\n\t\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\r\n\r\n\t\t\t\tparameters.gradientMap ? '#define USE_GRADIENTMAP' : '',\r\n\r\n\t\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\r\n\r\n\t\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\r\n\t\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\r\n\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\r\n\r\n\t\t\t\tparameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',\r\n\r\n\t\t\t\tparameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',\r\n\r\n\t\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\r\n\t\t\t\tparameters.logarithmicDepthBuffer && ( parameters.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\r\n\r\n\t\t\t\t( ( material.extensions ? material.extensions.shaderTextureLOD : false ) || parameters.envMap ) && ( parameters.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',\r\n\r\n\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t'uniform vec3 cameraPosition;',\r\n\t\t\t\t'uniform bool isOrthographic;',\r\n\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',\r\n\r\n\t\t\t\tparameters.dithering ? '#define DITHERING' : '',\r\n\r\n\t\t\t\t( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding || parameters.lightMapEncoding ) ?\r\n\t\t\t\t\tShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below\r\n\t\t\t\tparameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',\r\n\t\t\t\tparameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',\r\n\t\t\t\tparameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',\r\n\t\t\t\tparameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',\r\n\t\t\t\tparameters.lightMapEncoding ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',\r\n\t\t\t\tparameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',\r\n\r\n\t\t\t\tparameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',\r\n\r\n\t\t\t\t'\\n'\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t}\r\n\r\n\t\tvertexShader = resolveIncludes( vertexShader );\r\n\t\tvertexShader = replaceLightNums( vertexShader, parameters );\r\n\t\tvertexShader = replaceClippingPlaneNums( vertexShader, parameters );\r\n\r\n\t\tfragmentShader = resolveIncludes( fragmentShader );\r\n\t\tfragmentShader = replaceLightNums( fragmentShader, parameters );\r\n\t\tfragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );\r\n\r\n\t\tvertexShader = unrollLoops( vertexShader );\r\n\t\tfragmentShader = unrollLoops( fragmentShader );\r\n\r\n\t\tif ( parameters.isWebGL2 && ! material.isRawShaderMaterial ) {\r\n\r\n\t\t\tvar isGLSL3ShaderMaterial = false;\r\n\r\n\t\t\tvar versionRegex = /^\\s*#version\\s+300\\s+es\\s*\\n/;\r\n\r\n\t\t\tif ( material.isShaderMaterial &&\r\n\t\t\t\tvertexShader.match( versionRegex ) !== null &&\r\n\t\t\t\tfragmentShader.match( versionRegex ) !== null ) {\r\n\r\n\t\t\t\tisGLSL3ShaderMaterial = true;\r\n\r\n\t\t\t\tvertexShader = vertexShader.replace( versionRegex, '' );\r\n\t\t\t\tfragmentShader = fragmentShader.replace( versionRegex, '' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// GLSL 3.0 conversion\r\n\r\n\t\t\tprefixVertex = [\r\n\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t'#define attribute in',\r\n\t\t\t\t'#define varying out',\r\n\t\t\t\t'#define texture2D texture'\r\n\t\t\t].join( '\\n' ) + '\\n' + prefixVertex;\r\n\r\n\t\t\tprefixFragment = [\r\n\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t'#define varying in',\r\n\t\t\t\tisGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',\r\n\t\t\t\tisGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',\r\n\t\t\t\t'#define gl_FragDepthEXT gl_FragDepth',\r\n\t\t\t\t'#define texture2D texture',\r\n\t\t\t\t'#define textureCube texture',\r\n\t\t\t\t'#define texture2DProj textureProj',\r\n\t\t\t\t'#define texture2DLodEXT textureLod',\r\n\t\t\t\t'#define texture2DProjLodEXT textureProjLod',\r\n\t\t\t\t'#define textureCubeLodEXT textureLod',\r\n\t\t\t\t'#define texture2DGradEXT textureGrad',\r\n\t\t\t\t'#define texture2DProjGradEXT textureProjGrad',\r\n\t\t\t\t'#define textureCubeGradEXT textureGrad'\r\n\t\t\t].join( '\\n' ) + '\\n' + prefixFragment;\r\n\r\n\t\t\t// Multiview\r\n\r\n\t\t\tif ( numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\tprefixVertex = prefixVertex.replace(\r\n\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t\t'#extension GL_OVR_multiview2 : require',\r\n\t\t\t\t\t\t'layout(num_views = ' + numMultiviewViews + ') in;',\r\n\t\t\t\t\t\t'#define VIEW_ID gl_ViewID_OVR'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixVertex = prefixVertex.replace(\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 modelViewMatrix;',\r\n\t\t\t\t\t\t'uniform mat4 projectionMatrix;',\r\n\t\t\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t\t\t'uniform mat3 normalMatrix;'\r\n\t\t\t\t\t].join( '\\n' ),\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 modelViewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat4 projectionMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat4 viewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat3 normalMatrices[' + numMultiviewViews + '];',\r\n\r\n\t\t\t\t\t\t'#define modelViewMatrix modelViewMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define projectionMatrix projectionMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define viewMatrix viewMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define normalMatrix normalMatrices[VIEW_ID]'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixFragment = prefixFragment.replace(\r\n\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t\t'#extension GL_OVR_multiview2 : require',\r\n\t\t\t\t\t\t'#define VIEW_ID gl_ViewID_OVR'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixFragment = prefixFragment.replace(\r\n\t\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 viewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'#define viewMatrix viewMatrices[VIEW_ID]'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar vertexGlsl = prefixVertex + vertexShader;\r\n\t\tvar fragmentGlsl = prefixFragment + fragmentShader;\r\n\r\n\t\t// console.log( '*VERTEX*', vertexGlsl );\r\n\t\t// console.log( '*FRAGMENT*', fragmentGlsl );\r\n\r\n\t\tvar glVertexShader = WebGLShader( gl, 35633, vertexGlsl );\r\n\t\tvar glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );\r\n\r\n\t\tgl.attachShader( program, glVertexShader );\r\n\t\tgl.attachShader( program, glFragmentShader );\r\n\r\n\t\t// Force a particular attribute to index 0.\r\n\r\n\t\tif ( material.index0AttributeName !== undefined ) {\r\n\r\n\t\t\tgl.bindAttribLocation( program, 0, material.index0AttributeName );\r\n\r\n\t\t} else if ( parameters.morphTargets === true ) {\r\n\r\n\t\t\t// programs with morphTargets displace position out of attribute 0\r\n\t\t\tgl.bindAttribLocation( program, 0, 'position' );\r\n\r\n\t\t}\r\n\r\n\t\tgl.linkProgram( program );\r\n\r\n\t\t// check for link errors\r\n\t\tif ( renderer.debug.checkShaderErrors ) {\r\n\r\n\t\t\tvar programLog = gl.getProgramInfoLog( program ).trim();\r\n\t\t\tvar vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();\r\n\t\t\tvar fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();\r\n\r\n\t\t\tvar runnable = true;\r\n\t\t\tvar haveDiagnostics = true;\r\n\r\n\t\t\tif ( gl.getProgramParameter( program, 35714 ) === false ) {\r\n\r\n\t\t\t\trunnable = false;\r\n\r\n\t\t\t\tvar vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );\r\n\t\t\t\tvar fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );\r\n\r\n\t\t\t} else if ( programLog !== '' ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );\r\n\r\n\t\t\t} else if ( vertexLog === '' || fragmentLog === '' ) {\r\n\r\n\t\t\t\thaveDiagnostics = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( haveDiagnostics ) {\r\n\r\n\t\t\t\tthis.diagnostics = {\r\n\r\n\t\t\t\t\trunnable: runnable,\r\n\t\t\t\t\tmaterial: material,\r\n\r\n\t\t\t\t\tprogramLog: programLog,\r\n\r\n\t\t\t\t\tvertexShader: {\r\n\r\n\t\t\t\t\t\tlog: vertexLog,\r\n\t\t\t\t\t\tprefix: prefixVertex\r\n\r\n\t\t\t\t\t},\r\n\r\n\t\t\t\t\tfragmentShader: {\r\n\r\n\t\t\t\t\t\tlog: fragmentLog,\r\n\t\t\t\t\t\tprefix: prefixFragment\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// clean up\r\n\r\n\t\tgl.deleteShader( glVertexShader );\r\n\t\tgl.deleteShader( glFragmentShader );\r\n\r\n\t\t// set up caching for uniform locations\r\n\r\n\t\tvar cachedUniforms;\r\n\r\n\t\tthis.getUniforms = function () {\r\n\r\n\t\t\tif ( cachedUniforms === undefined ) {\r\n\r\n\t\t\t\tcachedUniforms = new WebGLUniforms( gl, program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn cachedUniforms;\r\n\r\n\t\t};\r\n\r\n\t\t// set up caching for attribute locations\r\n\r\n\t\tvar cachedAttributes;\r\n\r\n\t\tthis.getAttributes = function () {\r\n\r\n\t\t\tif ( cachedAttributes === undefined ) {\r\n\r\n\t\t\t\tcachedAttributes = fetchAttributeLocations( gl, program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn cachedAttributes;\r\n\r\n\t\t};\r\n\r\n\t\t// free resource\r\n\r\n\t\tthis.destroy = function () {\r\n\r\n\t\t\tgl.deleteProgram( program );\r\n\t\t\tthis.program = undefined;\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tthis.name = shader.name;\r\n\t\tthis.id = programIdCount ++;\r\n\t\tthis.cacheKey = cacheKey;\r\n\t\tthis.usedTimes = 1;\r\n\t\tthis.program = program;\r\n\t\tthis.vertexShader = glVertexShader;\r\n\t\tthis.fragmentShader = glFragmentShader;\r\n\t\tthis.numMultiviewViews = numMultiviewViews;\r\n\r\n\t\treturn this;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLPrograms( renderer, extensions, capabilities ) {\r\n\r\n\t\tvar programs = [];\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\t\tvar logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;\r\n\t\tvar floatVertexTextures = capabilities.floatVertexTextures;\r\n\t\tvar precision = capabilities.precision;\r\n\t\tvar maxVertexUniforms = capabilities.maxVertexUniforms;\r\n\t\tvar vertexTextures = capabilities.vertexTextures;\r\n\r\n\t\tvar shaderIDs = {\r\n\t\t\tMeshDepthMaterial: 'depth',\r\n\t\t\tMeshDistanceMaterial: 'distanceRGBA',\r\n\t\t\tMeshNormalMaterial: 'normal',\r\n\t\t\tMeshBasicMaterial: 'basic',\r\n\t\t\tMeshLambertMaterial: 'lambert',\r\n\t\t\tMeshPhongMaterial: 'phong',\r\n\t\t\tMeshToonMaterial: 'toon',\r\n\t\t\tMeshStandardMaterial: 'physical',\r\n\t\t\tMeshPhysicalMaterial: 'physical',\r\n\t\t\tMeshMatcapMaterial: 'matcap',\r\n\t\t\tLineBasicMaterial: 'basic',\r\n\t\t\tLineDashedMaterial: 'dashed',\r\n\t\t\tPointsMaterial: 'points',\r\n\t\t\tShadowMaterial: 'shadow',\r\n\t\t\tSpriteMaterial: 'sprite'\r\n\t\t};\r\n\r\n\t\tvar parameterNames = [\r\n\t\t\t\"precision\", \"isWebGL2\", \"supportsVertexTextures\", \"outputEncoding\", \"instancing\", \"numMultiviewViews\",\r\n\t\t\t\"map\", \"mapEncoding\", \"matcap\", \"matcapEncoding\", \"envMap\", \"envMapMode\", \"envMapEncoding\", \"envMapCubeUV\",\r\n\t\t\t\"lightMap\", \"lightMapEncoding\", \"aoMap\", \"emissiveMap\", \"emissiveMapEncoding\", \"bumpMap\", \"normalMap\", \"objectSpaceNormalMap\", \"tangentSpaceNormalMap\", \"clearcoatNormalMap\", \"displacementMap\", \"specularMap\",\r\n\t\t\t\"roughnessMap\", \"metalnessMap\", \"gradientMap\",\r\n\t\t\t\"alphaMap\", \"combine\", \"vertexColors\", \"vertexTangents\", \"vertexUvs\", \"uvsVertexOnly\", \"fog\", \"useFog\", \"fogExp2\",\r\n\t\t\t\"flatShading\", \"sizeAttenuation\", \"logarithmicDepthBuffer\", \"skinning\",\r\n\t\t\t\"maxBones\", \"useVertexTexture\", \"morphTargets\", \"morphNormals\",\r\n\t\t\t\"maxMorphTargets\", \"maxMorphNormals\", \"premultipliedAlpha\",\r\n\t\t\t\"numDirLights\", \"numPointLights\", \"numSpotLights\", \"numHemiLights\", \"numRectAreaLights\",\r\n\t\t\t\"numDirLightShadows\", \"numPointLightShadows\", \"numSpotLightShadows\",\r\n\t\t\t\"shadowMapEnabled\", \"shadowMapType\", \"toneMapping\", 'physicallyCorrectLights',\r\n\t\t\t\"alphaTest\", \"doubleSided\", \"flipSided\", \"numClippingPlanes\", \"numClipIntersection\", \"depthPacking\", \"dithering\",\r\n\t\t\t\"sheen\"\r\n\t\t];\r\n\r\n\r\n\t\tfunction allocateBones( object ) {\r\n\r\n\t\t\tvar skeleton = object.skeleton;\r\n\t\t\tvar bones = skeleton.bones;\r\n\r\n\t\t\tif ( floatVertexTextures ) {\r\n\r\n\t\t\t\treturn 1024;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// default for when object is not specified\r\n\t\t\t\t// ( for example when prebuilding shader to be used with multiple objects )\r\n\t\t\t\t//\r\n\t\t\t\t// - leave some extra space for other uniforms\r\n\t\t\t\t// - limit here is ANGLE's 254 max uniform vectors\r\n\t\t\t\t// (up to 54 should be safe)\r\n\r\n\t\t\t\tvar nVertexUniforms = maxVertexUniforms;\r\n\t\t\t\tvar nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );\r\n\r\n\t\t\t\tvar maxBones = Math.min( nVertexMatrices, bones.length );\r\n\r\n\t\t\t\tif ( maxBones < bones.length ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );\r\n\t\t\t\t\treturn 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn maxBones;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction getTextureEncodingFromMap( map, gammaOverrideLinear ) {\r\n\r\n\t\t\tvar encoding;\r\n\r\n\t\t\tif ( ! map ) {\r\n\r\n\t\t\t\tencoding = LinearEncoding;\r\n\r\n\t\t\t} else if ( map.isTexture ) {\r\n\r\n\t\t\t\tencoding = map.encoding;\r\n\r\n\t\t\t} else if ( map.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\tconsole.warn( \"THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\tencoding = map.texture.encoding;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.\r\n\t\t\tif ( encoding === LinearEncoding && gammaOverrideLinear ) {\r\n\r\n\t\t\t\tencoding = GammaEncoding;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn encoding;\r\n\r\n\t\t}\r\n\r\n\t\tthis.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {\r\n\r\n\t\t\tvar shaderID = shaderIDs[ material.type ];\r\n\r\n\t\t\t// heuristics to create shader parameters according to lights in the scene\r\n\t\t\t// (not to blow over maxLights budget)\r\n\r\n\t\t\tvar maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;\r\n\r\n\t\t\tif ( material.precision !== null ) {\r\n\r\n\t\t\t\tprecision = capabilities.getMaxPrecision( material.precision );\r\n\r\n\t\t\t\tif ( precision !== material.precision ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\t\t\tvar numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0;\r\n\r\n\t\t\tvar parameters = {\r\n\r\n\t\t\t\tisWebGL2: isWebGL2,\r\n\r\n\t\t\t\tshaderID: shaderID,\r\n\r\n\t\t\t\tprecision: precision,\r\n\r\n\t\t\t\tinstancing: object.isInstancedMesh === true,\r\n\r\n\t\t\t\tsupportsVertexTextures: vertexTextures,\r\n\t\t\t\tnumMultiviewViews: numMultiviewViews,\r\n\t\t\t\toutputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),\r\n\t\t\t\tmap: !! material.map,\r\n\t\t\t\tmapEncoding: getTextureEncodingFromMap( material.map ),\r\n\t\t\t\tmatcap: !! material.matcap,\r\n\t\t\t\tmatcapEncoding: getTextureEncodingFromMap( material.matcap ),\r\n\t\t\t\tenvMap: !! material.envMap,\r\n\t\t\t\tenvMapMode: material.envMap && material.envMap.mapping,\r\n\t\t\t\tenvMapEncoding: getTextureEncodingFromMap( material.envMap ),\r\n\t\t\t\tenvMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),\r\n\t\t\t\tlightMap: !! material.lightMap,\r\n\t\t\t\tlightMapEncoding: getTextureEncodingFromMap( material.lightMap ),\r\n\t\t\t\taoMap: !! material.aoMap,\r\n\t\t\t\temissiveMap: !! material.emissiveMap,\r\n\t\t\t\temissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),\r\n\t\t\t\tbumpMap: !! material.bumpMap,\r\n\t\t\t\tnormalMap: !! material.normalMap,\r\n\t\t\t\tobjectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,\r\n\t\t\t\ttangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,\r\n\t\t\t\tclearcoatNormalMap: !! material.clearcoatNormalMap,\r\n\t\t\t\tdisplacementMap: !! material.displacementMap,\r\n\t\t\t\troughnessMap: !! material.roughnessMap,\r\n\t\t\t\tmetalnessMap: !! material.metalnessMap,\r\n\t\t\t\tspecularMap: !! material.specularMap,\r\n\t\t\t\talphaMap: !! material.alphaMap,\r\n\r\n\t\t\t\tgradientMap: !! material.gradientMap,\r\n\r\n\t\t\t\tsheen: !! material.sheen,\r\n\r\n\t\t\t\tcombine: material.combine,\r\n\r\n\t\t\t\tvertexTangents: ( material.normalMap && material.vertexTangents ),\r\n\t\t\t\tvertexColors: material.vertexColors,\r\n\t\t\t\tvertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,\r\n\t\t\t\tuvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,\r\n\r\n\t\t\t\tfog: !! fog,\r\n\t\t\t\tuseFog: material.fog,\r\n\t\t\t\tfogExp2: ( fog && fog.isFogExp2 ),\r\n\r\n\t\t\t\tflatShading: material.flatShading,\r\n\r\n\t\t\t\tsizeAttenuation: material.sizeAttenuation,\r\n\t\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\r\n\r\n\t\t\t\tskinning: material.skinning && maxBones > 0,\r\n\t\t\t\tmaxBones: maxBones,\r\n\t\t\t\tuseVertexTexture: floatVertexTextures,\r\n\r\n\t\t\t\tmorphTargets: material.morphTargets,\r\n\t\t\t\tmorphNormals: material.morphNormals,\r\n\t\t\t\tmaxMorphTargets: renderer.maxMorphTargets,\r\n\t\t\t\tmaxMorphNormals: renderer.maxMorphNormals,\r\n\r\n\t\t\t\tnumDirLights: lights.directional.length,\r\n\t\t\t\tnumPointLights: lights.point.length,\r\n\t\t\t\tnumSpotLights: lights.spot.length,\r\n\t\t\t\tnumRectAreaLights: lights.rectArea.length,\r\n\t\t\t\tnumHemiLights: lights.hemi.length,\r\n\r\n\t\t\t\tnumDirLightShadows: lights.directionalShadowMap.length,\r\n\t\t\t\tnumPointLightShadows: lights.pointShadowMap.length,\r\n\t\t\t\tnumSpotLightShadows: lights.spotShadowMap.length,\r\n\r\n\t\t\t\tnumClippingPlanes: nClipPlanes,\r\n\t\t\t\tnumClipIntersection: nClipIntersection,\r\n\r\n\t\t\t\tdithering: material.dithering,\r\n\r\n\t\t\t\tshadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,\r\n\t\t\t\tshadowMapType: renderer.shadowMap.type,\r\n\r\n\t\t\t\ttoneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,\r\n\t\t\t\tphysicallyCorrectLights: renderer.physicallyCorrectLights,\r\n\r\n\t\t\t\tpremultipliedAlpha: material.premultipliedAlpha,\r\n\r\n\t\t\t\talphaTest: material.alphaTest,\r\n\t\t\t\tdoubleSided: material.side === DoubleSide,\r\n\t\t\t\tflipSided: material.side === BackSide,\r\n\r\n\t\t\t\tdepthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false\r\n\r\n\t\t\t};\r\n\r\n\t\t\treturn parameters;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getProgramCacheKey = function ( material, parameters ) {\r\n\r\n\t\t\tvar array = [];\r\n\r\n\t\t\tif ( parameters.shaderID ) {\r\n\r\n\t\t\t\tarray.push( parameters.shaderID );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tarray.push( material.fragmentShader );\r\n\t\t\t\tarray.push( material.vertexShader );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.defines !== undefined ) {\r\n\r\n\t\t\t\tfor ( var name in material.defines ) {\r\n\r\n\t\t\t\t\tarray.push( name );\r\n\t\t\t\t\tarray.push( material.defines[ name ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < parameterNames.length; i ++ ) {\r\n\r\n\t\t\t\tarray.push( parameters[ parameterNames[ i ] ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tarray.push( material.onBeforeCompile.toString() );\r\n\r\n\t\t\tarray.push( renderer.gammaOutput );\r\n\r\n\t\t\tarray.push( renderer.gammaFactor );\r\n\r\n\t\t\treturn array.join();\r\n\r\n\t\t};\r\n\r\n\t\tthis.acquireProgram = function ( material, shader, parameters, cacheKey ) {\r\n\r\n\t\t\tvar program;\r\n\r\n\t\t\t// Check if code has been already compiled\r\n\t\t\tfor ( var p = 0, pl = programs.length; p < pl; p ++ ) {\r\n\r\n\t\t\t\tvar preexistingProgram = programs[ p ];\r\n\r\n\t\t\t\tif ( preexistingProgram.cacheKey === cacheKey ) {\r\n\r\n\t\t\t\t\tprogram = preexistingProgram;\r\n\t\t\t\t\t++ program.usedTimes;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( program === undefined ) {\r\n\r\n\t\t\t\tprogram = new WebGLProgram( renderer, extensions, cacheKey, material, shader, parameters );\r\n\t\t\t\tprograms.push( program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn program;\r\n\r\n\t\t};\r\n\r\n\t\tthis.releaseProgram = function ( program ) {\r\n\r\n\t\t\tif ( -- program.usedTimes === 0 ) {\r\n\r\n\t\t\t\t// Remove from unordered set\r\n\t\t\t\tvar i = programs.indexOf( program );\r\n\t\t\t\tprograms[ i ] = programs[ programs.length - 1 ];\r\n\t\t\t\tprograms.pop();\r\n\r\n\t\t\t\t// Free WebGL resources\r\n\t\t\t\tprogram.destroy();\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\t// Exposed for resource monitoring & error feedback via renderer.info:\r\n\t\tthis.programs = programs;\r\n\r\n\t}\n\n\t/**\r\n\t * @author fordacious / fordacious.github.io\r\n\t */\r\n\r\n\tfunction WebGLProperties() {\r\n\r\n\t\tvar properties = new WeakMap();\r\n\r\n\t\tfunction get( object ) {\r\n\r\n\t\t\tvar map = properties.get( object );\r\n\r\n\t\t\tif ( map === undefined ) {\r\n\r\n\t\t\t\tmap = {};\r\n\t\t\t\tproperties.set( object, map );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn map;\r\n\r\n\t\t}\r\n\r\n\t\tfunction remove( object ) {\r\n\r\n\t\t\tproperties.delete( object );\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( object, key, value ) {\r\n\r\n\t\t\tproperties.get( object )[ key ] = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tproperties = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tremove: remove,\r\n\t\t\tupdate: update,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction painterSortStable( a, b ) {\r\n\r\n\t\tif ( a.groupOrder !== b.groupOrder ) {\r\n\r\n\t\t\treturn a.groupOrder - b.groupOrder;\r\n\r\n\t\t} else if ( a.renderOrder !== b.renderOrder ) {\r\n\r\n\t\t\treturn a.renderOrder - b.renderOrder;\r\n\r\n\t\t} else if ( a.program !== b.program ) {\r\n\r\n\t\t\treturn a.program.id - b.program.id;\r\n\r\n\t\t} else if ( a.material.id !== b.material.id ) {\r\n\r\n\t\t\treturn a.material.id - b.material.id;\r\n\r\n\t\t} else if ( a.z !== b.z ) {\r\n\r\n\t\t\treturn a.z - b.z;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn a.id - b.id;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction reversePainterSortStable( a, b ) {\r\n\r\n\t\tif ( a.groupOrder !== b.groupOrder ) {\r\n\r\n\t\t\treturn a.groupOrder - b.groupOrder;\r\n\r\n\t\t} else if ( a.renderOrder !== b.renderOrder ) {\r\n\r\n\t\t\treturn a.renderOrder - b.renderOrder;\r\n\r\n\t\t} else if ( a.z !== b.z ) {\r\n\r\n\t\t\treturn b.z - a.z;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn a.id - b.id;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\r\n\tfunction WebGLRenderList() {\r\n\r\n\t\tvar renderItems = [];\r\n\t\tvar renderItemsIndex = 0;\r\n\r\n\t\tvar opaque = [];\r\n\t\tvar transparent = [];\r\n\r\n\t\tvar defaultProgram = { id: - 1 };\r\n\r\n\t\tfunction init() {\r\n\r\n\t\t\trenderItemsIndex = 0;\r\n\r\n\t\t\topaque.length = 0;\r\n\t\t\ttransparent.length = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getNextRenderItem( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = renderItems[ renderItemsIndex ];\r\n\r\n\t\t\tif ( renderItem === undefined ) {\r\n\r\n\t\t\t\trenderItem = {\r\n\t\t\t\t\tid: object.id,\r\n\t\t\t\t\tobject: object,\r\n\t\t\t\t\tgeometry: geometry,\r\n\t\t\t\t\tmaterial: material,\r\n\t\t\t\t\tprogram: material.program || defaultProgram,\r\n\t\t\t\t\tgroupOrder: groupOrder,\r\n\t\t\t\t\trenderOrder: object.renderOrder,\r\n\t\t\t\t\tz: z,\r\n\t\t\t\t\tgroup: group\r\n\t\t\t\t};\r\n\r\n\t\t\t\trenderItems[ renderItemsIndex ] = renderItem;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderItem.id = object.id;\r\n\t\t\t\trenderItem.object = object;\r\n\t\t\t\trenderItem.geometry = geometry;\r\n\t\t\t\trenderItem.material = material;\r\n\t\t\t\trenderItem.program = material.program || defaultProgram;\r\n\t\t\t\trenderItem.groupOrder = groupOrder;\r\n\t\t\t\trenderItem.renderOrder = object.renderOrder;\r\n\t\t\t\trenderItem.z = z;\r\n\t\t\t\trenderItem.group = group;\r\n\r\n\t\t\t}\r\n\r\n\t\t\trenderItemsIndex ++;\r\n\r\n\t\t\treturn renderItem;\r\n\r\n\t\t}\r\n\r\n\t\tfunction push( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\r\n\r\n\t\t\t( material.transparent === true ? transparent : opaque ).push( renderItem );\r\n\r\n\t\t}\r\n\r\n\t\tfunction unshift( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\r\n\r\n\t\t\t( material.transparent === true ? transparent : opaque ).unshift( renderItem );\r\n\r\n\t\t}\r\n\r\n\t\tfunction sort() {\r\n\r\n\t\t\tif ( opaque.length > 1 ) { opaque.sort( painterSortStable ); }\r\n\t\t\tif ( transparent.length > 1 ) { transparent.sort( reversePainterSortStable ); }\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\topaque: opaque,\r\n\t\t\ttransparent: transparent,\r\n\r\n\t\t\tinit: init,\r\n\t\t\tpush: push,\r\n\t\t\tunshift: unshift,\r\n\r\n\t\t\tsort: sort\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction WebGLRenderLists() {\r\n\r\n\t\tvar lists = new WeakMap();\r\n\r\n\t\tfunction onSceneDispose( event ) {\r\n\r\n\t\t\tvar scene = event.target;\r\n\r\n\t\t\tscene.removeEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\tlists.delete( scene );\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( scene, camera ) {\r\n\r\n\t\t\tvar cameras = lists.get( scene );\r\n\t\t\tvar list;\r\n\t\t\tif ( cameras === undefined ) {\r\n\r\n\t\t\t\tlist = new WebGLRenderList();\r\n\t\t\t\tlists.set( scene, new WeakMap() );\r\n\t\t\t\tlists.get( scene ).set( camera, list );\r\n\r\n\t\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tlist = cameras.get( camera );\r\n\t\t\t\tif ( list === undefined ) {\r\n\r\n\t\t\t\t\tlist = new WebGLRenderList();\r\n\t\t\t\t\tcameras.set( camera, list );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn list;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tlists = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction UniformsCache() {\r\n\r\n\t\tvar lights = {};\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: function ( light ) {\r\n\r\n\t\t\t\tif ( lights[ light.id ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn lights[ light.id ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar uniforms;\r\n\r\n\t\t\t\tswitch ( light.type ) {\r\n\r\n\t\t\t\t\tcase 'DirectionalLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'SpotLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tdistance: 0,\r\n\t\t\t\t\t\t\tconeCos: 0,\r\n\t\t\t\t\t\t\tpenumbraCos: 0,\r\n\t\t\t\t\t\t\tdecay: 0,\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'PointLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tdistance: 0,\r\n\t\t\t\t\t\t\tdecay: 0,\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2(),\r\n\t\t\t\t\t\t\tshadowCameraNear: 1,\r\n\t\t\t\t\t\t\tshadowCameraFar: 1000\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'HemisphereLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tskyColor: new Color(),\r\n\t\t\t\t\t\t\tgroundColor: new Color()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'RectAreaLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\thalfWidth: new Vector3(),\r\n\t\t\t\t\t\t\thalfHeight: new Vector3()\r\n\t\t\t\t\t\t\t// TODO (abelnation): set RectAreaLight shadow uniforms\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlights[ light.id ] = uniforms;\r\n\r\n\t\t\t\treturn uniforms;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tvar nextVersion = 0;\r\n\r\n\tfunction shadowCastingLightsFirst( lightA, lightB ) {\r\n\r\n\t\treturn ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );\r\n\r\n\t}\r\n\r\n\tfunction WebGLLights() {\r\n\r\n\t\tvar cache = new UniformsCache();\r\n\r\n\t\tvar state = {\r\n\r\n\t\t\tversion: 0,\r\n\r\n\t\t\thash: {\r\n\t\t\t\tdirectionalLength: - 1,\r\n\t\t\t\tpointLength: - 1,\r\n\t\t\t\tspotLength: - 1,\r\n\t\t\t\trectAreaLength: - 1,\r\n\t\t\t\themiLength: - 1,\r\n\r\n\t\t\t\tnumDirectionalShadows: - 1,\r\n\t\t\t\tnumPointShadows: - 1,\r\n\t\t\t\tnumSpotShadows: - 1,\r\n\t\t\t},\r\n\r\n\t\t\tambient: [ 0, 0, 0 ],\r\n\t\t\tprobe: [],\r\n\t\t\tdirectional: [],\r\n\t\t\tdirectionalShadowMap: [],\r\n\t\t\tdirectionalShadowMatrix: [],\r\n\t\t\tspot: [],\r\n\t\t\tspotShadowMap: [],\r\n\t\t\tspotShadowMatrix: [],\r\n\t\t\trectArea: [],\r\n\t\t\tpoint: [],\r\n\t\t\tpointShadowMap: [],\r\n\t\t\tpointShadowMatrix: [],\r\n\t\t\themi: [],\r\n\r\n\t\t\tnumDirectionalShadows: - 1,\r\n\t\t\tnumPointShadows: - 1,\r\n\t\t\tnumSpotShadows: - 1\r\n\r\n\t\t};\r\n\r\n\t\tfor ( var i = 0; i < 9; i ++ ) { state.probe.push( new Vector3() ); }\r\n\r\n\t\tvar vector3 = new Vector3();\r\n\t\tvar matrix4 = new Matrix4();\r\n\t\tvar matrix42 = new Matrix4();\r\n\r\n\t\tfunction setup( lights, shadows, camera ) {\r\n\r\n\t\t\tvar r = 0, g = 0, b = 0;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) { state.probe[ i ].set( 0, 0, 0 ); }\r\n\r\n\t\t\tvar directionalLength = 0;\r\n\t\t\tvar pointLength = 0;\r\n\t\t\tvar spotLength = 0;\r\n\t\t\tvar rectAreaLength = 0;\r\n\t\t\tvar hemiLength = 0;\r\n\r\n\t\t\tvar numDirectionalShadows = 0;\r\n\t\t\tvar numPointShadows = 0;\r\n\t\t\tvar numSpotShadows = 0;\r\n\r\n\t\t\tvar viewMatrix = camera.matrixWorldInverse;\r\n\r\n\t\t\tlights.sort( shadowCastingLightsFirst );\r\n\r\n\t\t\tfor ( var i = 0, l = lights.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar light = lights[ i ];\r\n\r\n\t\t\t\tvar color = light.color;\r\n\t\t\t\tvar intensity = light.intensity;\r\n\t\t\t\tvar distance = light.distance;\r\n\r\n\t\t\t\tvar shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;\r\n\r\n\t\t\t\tif ( light.isAmbientLight ) {\r\n\r\n\t\t\t\t\tr += color.r * intensity;\r\n\t\t\t\t\tg += color.g * intensity;\r\n\t\t\t\t\tb += color.b * intensity;\r\n\r\n\t\t\t\t} else if ( light.isLightProbe ) {\r\n\r\n\t\t\t\t\tfor ( var j = 0; j < 9; j ++ ) {\r\n\r\n\t\t\t\t\t\tstate.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( light.isDirectionalLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.sub( vector3 );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\r\n\t\t\t\t\t\tstate.directionalShadowMap[ directionalLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumDirectionalShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.directional[ directionalLength ] = uniforms;\r\n\r\n\t\t\t\t\tdirectionalLength ++;\r\n\r\n\t\t\t\t} else if ( light.isSpotLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\r\n\t\t\t\t\tuniforms.distance = distance;\r\n\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.sub( vector3 );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.coneCos = Math.cos( light.angle );\r\n\t\t\t\t\tuniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );\r\n\t\t\t\t\tuniforms.decay = light.decay;\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\r\n\t\t\t\t\t\tstate.spotShadowMap[ spotLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.spotShadowMatrix[ spotLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumSpotShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.spot[ spotLength ] = uniforms;\r\n\r\n\t\t\t\t\tspotLength ++;\r\n\r\n\t\t\t\t} else if ( light.isRectAreaLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\t// (a) intensity is the total visible light emitted\r\n\t\t\t\t\t//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );\r\n\r\n\t\t\t\t\t// (b) intensity is the brightness of the light\r\n\t\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\t// extract local rotation of light to derive width/height half vectors\r\n\t\t\t\t\tmatrix42.identity();\r\n\t\t\t\t\tmatrix4.copy( light.matrixWorld );\r\n\t\t\t\t\tmatrix4.premultiply( viewMatrix );\r\n\t\t\t\t\tmatrix42.extractRotation( matrix4 );\r\n\r\n\t\t\t\t\tuniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );\r\n\t\t\t\t\tuniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );\r\n\r\n\t\t\t\t\tuniforms.halfWidth.applyMatrix4( matrix42 );\r\n\t\t\t\t\tuniforms.halfHeight.applyMatrix4( matrix42 );\r\n\r\n\t\t\t\t\t// TODO (abelnation): RectAreaLight distance?\r\n\t\t\t\t\t// uniforms.distance = distance;\r\n\r\n\t\t\t\t\tstate.rectArea[ rectAreaLength ] = uniforms;\r\n\r\n\t\t\t\t\trectAreaLength ++;\r\n\r\n\t\t\t\t} else if ( light.isPointLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\r\n\t\t\t\t\tuniforms.distance = light.distance;\r\n\t\t\t\t\tuniforms.decay = light.decay;\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\t\t\t\t\t\tuniforms.shadowCameraNear = shadow.camera.near;\r\n\t\t\t\t\t\tuniforms.shadowCameraFar = shadow.camera.far;\r\n\r\n\t\t\t\t\t\tstate.pointShadowMap[ pointLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.pointShadowMatrix[ pointLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumPointShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.point[ pointLength ] = uniforms;\r\n\r\n\t\t\t\t\tpointLength ++;\r\n\r\n\t\t\t\t} else if ( light.isHemisphereLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\t\t\t\t\tuniforms.direction.normalize();\r\n\r\n\t\t\t\t\tuniforms.skyColor.copy( light.color ).multiplyScalar( intensity );\r\n\t\t\t\t\tuniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );\r\n\r\n\t\t\t\t\tstate.hemi[ hemiLength ] = uniforms;\r\n\r\n\t\t\t\t\themiLength ++;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.ambient[ 0 ] = r;\r\n\t\t\tstate.ambient[ 1 ] = g;\r\n\t\t\tstate.ambient[ 2 ] = b;\r\n\r\n\t\t\tvar hash = state.hash;\r\n\r\n\t\t\tif ( hash.directionalLength !== directionalLength ||\r\n\t\t\t\thash.pointLength !== pointLength ||\r\n\t\t\t\thash.spotLength !== spotLength ||\r\n\t\t\t\thash.rectAreaLength !== rectAreaLength ||\r\n\t\t\t\thash.hemiLength !== hemiLength ||\r\n\t\t\t\thash.numDirectionalShadows !== numDirectionalShadows ||\r\n\t\t\t\thash.numPointShadows !== numPointShadows ||\r\n\t\t\t\thash.numSpotShadows !== numSpotShadows ) {\r\n\r\n\t\t\t\tstate.directional.length = directionalLength;\r\n\t\t\t\tstate.spot.length = spotLength;\r\n\t\t\t\tstate.rectArea.length = rectAreaLength;\r\n\t\t\t\tstate.point.length = pointLength;\r\n\t\t\t\tstate.hemi.length = hemiLength;\r\n\r\n\t\t\t\tstate.directionalShadowMap.length = numDirectionalShadows;\r\n\t\t\t\tstate.pointShadowMap.length = numPointShadows;\r\n\t\t\t\tstate.spotShadowMap.length = numSpotShadows;\r\n\t\t\t\tstate.directionalShadowMatrix.length = numDirectionalShadows;\r\n\t\t\t\tstate.pointShadowMatrix.length = numPointShadows;\r\n\t\t\t\tstate.spotShadowMatrix.length = numSpotShadows;\r\n\r\n\t\t\t\thash.directionalLength = directionalLength;\r\n\t\t\t\thash.pointLength = pointLength;\r\n\t\t\t\thash.spotLength = spotLength;\r\n\t\t\t\thash.rectAreaLength = rectAreaLength;\r\n\t\t\t\thash.hemiLength = hemiLength;\r\n\r\n\t\t\t\thash.numDirectionalShadows = numDirectionalShadows;\r\n\t\t\t\thash.numPointShadows = numPointShadows;\r\n\t\t\t\thash.numSpotShadows = numSpotShadows;\r\n\r\n\t\t\t\tstate.version = nextVersion ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tsetup: setup,\r\n\t\t\tstate: state\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WebGLRenderState() {\r\n\r\n\t\tvar lights = new WebGLLights();\r\n\r\n\t\tvar lightsArray = [];\r\n\t\tvar shadowsArray = [];\r\n\r\n\t\tfunction init() {\r\n\r\n\t\t\tlightsArray.length = 0;\r\n\t\t\tshadowsArray.length = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushLight( light ) {\r\n\r\n\t\t\tlightsArray.push( light );\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushShadow( shadowLight ) {\r\n\r\n\t\t\tshadowsArray.push( shadowLight );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setupLights( camera ) {\r\n\r\n\t\t\tlights.setup( lightsArray, shadowsArray, camera );\r\n\r\n\t\t}\r\n\r\n\t\tvar state = {\r\n\t\t\tlightsArray: lightsArray,\r\n\t\t\tshadowsArray: shadowsArray,\r\n\r\n\t\t\tlights: lights\r\n\t\t};\r\n\r\n\t\treturn {\r\n\t\t\tinit: init,\r\n\t\t\tstate: state,\r\n\t\t\tsetupLights: setupLights,\r\n\r\n\t\t\tpushLight: pushLight,\r\n\t\t\tpushShadow: pushShadow\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction WebGLRenderStates() {\r\n\r\n\t\tvar renderStates = new WeakMap();\r\n\r\n\t\tfunction onSceneDispose( event ) {\r\n\r\n\t\t\tvar scene = event.target;\r\n\r\n\t\t\tscene.removeEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\trenderStates.delete( scene );\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( scene, camera ) {\r\n\r\n\t\t\tvar renderState;\r\n\r\n\t\t\tif ( renderStates.has( scene ) === false ) {\r\n\r\n\t\t\t\trenderState = new WebGLRenderState();\r\n\t\t\t\trenderStates.set( scene, new WeakMap() );\r\n\t\t\t\trenderStates.get( scene ).set( camera, renderState );\r\n\r\n\t\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( renderStates.get( scene ).has( camera ) === false ) {\r\n\r\n\t\t\t\t\trenderState = new WebGLRenderState();\r\n\t\t\t\t\trenderStates.get( scene ).set( camera, renderState );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderState = renderStates.get( scene ).get( camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn renderState;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\trenderStates = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author bhouston / https://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshDepthMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshDepthMaterial';\r\n\r\n\t\tthis.depthPacking = BasicDepthPacking;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshDepthMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshDepthMaterial.prototype.constructor = MeshDepthMaterial;\r\n\r\n\tMeshDepthMaterial.prototype.isMeshDepthMaterial = true;\r\n\r\n\tMeshDepthMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.depthPacking = source.depthPacking;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * referencePosition: ,\r\n\t * nearDistance: ,\r\n\t * farDistance: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: \r\n\t *\r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshDistanceMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshDistanceMaterial';\r\n\r\n\t\tthis.referencePosition = new Vector3();\r\n\t\tthis.nearDistance = 1;\r\n\t\tthis.farDistance = 1000;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshDistanceMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;\r\n\r\n\tMeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;\r\n\r\n\tMeshDistanceMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.referencePosition.copy( source.referencePosition );\r\n\t\tthis.nearDistance = source.nearDistance;\r\n\t\tthis.farDistance = source.farDistance;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tvar vsm_frag = \"uniform sampler2D shadow_pass;\\nuniform vec2 resolution;\\nuniform float radius;\\n#include \\nvoid main() {\\n float mean = 0.0;\\n float squared_mean = 0.0;\\n\\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\\n #ifdef HORIZONAL_PASS\\n vec2 distribution = unpack2HalfToRGBA ( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\\n mean += distribution.x;\\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\\n #else\\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\\n mean += depth;\\n squared_mean += depth * depth;\\n #endif\\n }\\n mean = mean * HALF_SAMPLE_RATE;\\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\\n float std_dev = sqrt( squared_mean - mean * mean );\\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\\n}\";\n\n\tvar vsm_vert = \"void main() {\\n\\tgl_Position = vec4( position, 1.0 );\\n}\";\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLShadowMap( _renderer, _objects, maxTextureSize ) {\r\n\r\n\t\tvar _frustum = new Frustum(),\r\n\r\n\t\t\t_shadowMapSize = new Vector2(),\r\n\t\t\t_viewportSize = new Vector2(),\r\n\r\n\t\t\t_viewport = new Vector4(),\r\n\r\n\t\t\t_depthMaterials = [],\r\n\t\t\t_distanceMaterials = [],\r\n\r\n\t\t\t_materialCache = {};\r\n\r\n\t\tvar shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };\r\n\r\n\t\tvar shadowMaterialVertical = new ShaderMaterial( {\r\n\r\n\t\t\tdefines: {\r\n\t\t\t\tSAMPLE_RATE: 2.0 / 8.0,\r\n\t\t\t\tHALF_SAMPLE_RATE: 1.0 / 8.0\r\n\t\t\t},\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\tshadow_pass: { value: null },\r\n\t\t\t\tresolution: { value: new Vector2() },\r\n\t\t\t\tradius: { value: 4.0 }\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: vsm_vert,\r\n\r\n\t\t\tfragmentShader: vsm_frag\r\n\r\n\t\t} );\r\n\r\n\t\tvar shadowMaterialHorizonal = shadowMaterialVertical.clone();\r\n\t\tshadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;\r\n\r\n\t\tvar fullScreenTri = new BufferGeometry();\r\n\t\tfullScreenTri.setAttribute(\r\n\t\t\t\"position\",\r\n\t\t\tnew BufferAttribute(\r\n\t\t\t\tnew Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),\r\n\t\t\t\t3\r\n\t\t\t)\r\n\t\t);\r\n\r\n\t\tvar fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.autoUpdate = true;\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t\tthis.type = PCFShadowMap;\r\n\r\n\t\tthis.render = function ( lights, scene, camera ) {\r\n\r\n\t\t\tif ( scope.enabled === false ) { return; }\r\n\t\t\tif ( scope.autoUpdate === false && scope.needsUpdate === false ) { return; }\r\n\r\n\t\t\tif ( lights.length === 0 ) { return; }\r\n\r\n\t\t\tvar currentRenderTarget = _renderer.getRenderTarget();\r\n\t\t\tvar activeCubeFace = _renderer.getActiveCubeFace();\r\n\t\t\tvar activeMipmapLevel = _renderer.getActiveMipmapLevel();\r\n\r\n\t\t\tvar _state = _renderer.state;\r\n\r\n\t\t\t// Set GL state for depth map.\r\n\t\t\t_state.setBlending( NoBlending );\r\n\t\t\t_state.buffers.color.setClear( 1, 1, 1, 1 );\r\n\t\t\t_state.buffers.depth.setTest( true );\r\n\t\t\t_state.setScissorTest( false );\r\n\r\n\t\t\t// render depth map\r\n\r\n\t\t\tfor ( var i = 0, il = lights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar light = lights[ i ];\r\n\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\tif ( shadow === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_shadowMapSize.copy( shadow.mapSize );\r\n\r\n\t\t\t\tvar shadowFrameExtents = shadow.getFrameExtents();\r\n\r\n\t\t\t\t_shadowMapSize.multiply( shadowFrameExtents );\r\n\r\n\t\t\t\t_viewportSize.copy( shadow.mapSize );\r\n\r\n\t\t\t\tif ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has shadow exceeding max texture size, reducing' );\r\n\r\n\t\t\t\t\tif ( _shadowMapSize.x > maxTextureSize ) {\r\n\r\n\t\t\t\t\t\t_viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );\r\n\t\t\t\t\t\t_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;\r\n\t\t\t\t\t\tshadow.mapSize.x = _viewportSize.x;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( _shadowMapSize.y > maxTextureSize ) {\r\n\r\n\t\t\t\t\t\t_viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );\r\n\t\t\t\t\t\t_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;\r\n\t\t\t\t\t\tshadow.mapSize.y = _viewportSize.y;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\r\n\r\n\t\t\t\t\tvar pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };\r\n\r\n\t\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\t\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\r\n\r\n\t\t\t\t\tshadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\r\n\t\t\t\t\tshadow.camera.updateProjectionMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( shadow.map === null ) {\r\n\r\n\t\t\t\t\tvar pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };\r\n\r\n\t\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\t\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\r\n\r\n\t\t\t\t\tshadow.camera.updateProjectionMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_renderer.setRenderTarget( shadow.map );\r\n\t\t\t\t_renderer.clear();\r\n\r\n\t\t\t\tvar viewportCount = shadow.getViewportCount();\r\n\r\n\t\t\t\tfor ( var vp = 0; vp < viewportCount; vp ++ ) {\r\n\r\n\t\t\t\t\tvar viewport = shadow.getViewport( vp );\r\n\r\n\t\t\t\t\t_viewport.set(\r\n\t\t\t\t\t\t_viewportSize.x * viewport.x,\r\n\t\t\t\t\t\t_viewportSize.y * viewport.y,\r\n\t\t\t\t\t\t_viewportSize.x * viewport.z,\r\n\t\t\t\t\t\t_viewportSize.y * viewport.w\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\t_state.viewport( _viewport );\r\n\r\n\t\t\t\t\tshadow.updateMatrices( light, vp );\r\n\r\n\t\t\t\t\t_frustum = shadow.getFrustum();\r\n\r\n\t\t\t\t\trenderObject( scene, camera, shadow.camera, light, this.type );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// do blur pass for VSM\r\n\r\n\t\t\t\tif ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\r\n\r\n\t\t\t\t\tVSMPass( shadow, camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.needsUpdate = false;\r\n\r\n\t\t\t_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\r\n\r\n\t\t};\r\n\r\n\t\tfunction VSMPass( shadow, camera ) {\r\n\r\n\t\t\tvar geometry = _objects.update( fullScreenMesh );\r\n\r\n\t\t\t// vertical pass\r\n\r\n\t\t\tshadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;\r\n\t\t\tshadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;\r\n\t\t\tshadowMaterialVertical.uniforms.radius.value = shadow.radius;\r\n\t\t\t_renderer.setRenderTarget( shadow.mapPass );\r\n\t\t\t_renderer.clear();\r\n\t\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );\r\n\r\n\t\t\t// horizonal pass\r\n\r\n\t\t\tshadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;\r\n\t\t\tshadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;\r\n\t\t\tshadowMaterialHorizonal.uniforms.radius.value = shadow.radius;\r\n\t\t\t_renderer.setRenderTarget( shadow.map );\r\n\t\t\t_renderer.clear();\r\n\t\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {\r\n\r\n\t\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\r\n\r\n\t\t\tvar material = _depthMaterials[ index ];\r\n\r\n\t\t\tif ( material === undefined ) {\r\n\r\n\t\t\t\tmaterial = new MeshDepthMaterial( {\r\n\r\n\t\t\t\t\tdepthPacking: RGBADepthPacking,\r\n\r\n\t\t\t\t\tmorphTargets: useMorphing,\r\n\t\t\t\t\tskinning: useSkinning\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t_depthMaterials[ index ] = material;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {\r\n\r\n\t\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\r\n\r\n\t\t\tvar material = _distanceMaterials[ index ];\r\n\r\n\t\t\tif ( material === undefined ) {\r\n\r\n\t\t\t\tmaterial = new MeshDistanceMaterial( {\r\n\r\n\t\t\t\t\tmorphTargets: useMorphing,\r\n\t\t\t\t\tskinning: useSkinning\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t_distanceMaterials[ index ] = material;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tvar result = null;\r\n\r\n\t\t\tvar getMaterialVariant = getDepthMaterialVariant;\r\n\t\t\tvar customMaterial = object.customDepthMaterial;\r\n\r\n\t\t\tif ( light.isPointLight === true ) {\r\n\r\n\t\t\t\tgetMaterialVariant = getDistanceMaterialVariant;\r\n\t\t\t\tcustomMaterial = object.customDistanceMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( customMaterial === undefined ) {\r\n\r\n\t\t\t\tvar useMorphing = false;\r\n\r\n\t\t\t\tif ( material.morphTargets === true ) {\r\n\r\n\t\t\t\t\tif ( geometry.isBufferGeometry === true ) {\r\n\r\n\t\t\t\t\t\tuseMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;\r\n\r\n\t\t\t\t\t} else if ( geometry.isGeometry === true ) {\r\n\r\n\t\t\t\t\t\tuseMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar useSkinning = false;\r\n\r\n\t\t\t\tif ( object.isSkinnedMesh === true ) {\r\n\r\n\t\t\t\t\tif ( material.skinning === true ) {\r\n\r\n\t\t\t\t\t\tuseSkinning = true;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar useInstancing = object.isInstancedMesh === true;\r\n\r\n\t\t\t\tresult = getMaterialVariant( useMorphing, useSkinning, useInstancing );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresult = customMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _renderer.localClippingEnabled &&\r\n\t\t\t\t\tmaterial.clipShadows === true &&\r\n\t\t\t\t\tmaterial.clippingPlanes.length !== 0 ) {\r\n\r\n\t\t\t\t// in this case we need a unique material instance reflecting the\r\n\t\t\t\t// appropriate state\r\n\r\n\t\t\t\tvar keyA = result.uuid, keyB = material.uuid;\r\n\r\n\t\t\t\tvar materialsForVariant = _materialCache[ keyA ];\r\n\r\n\t\t\t\tif ( materialsForVariant === undefined ) {\r\n\r\n\t\t\t\t\tmaterialsForVariant = {};\r\n\t\t\t\t\t_materialCache[ keyA ] = materialsForVariant;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar cachedMaterial = materialsForVariant[ keyB ];\r\n\r\n\t\t\t\tif ( cachedMaterial === undefined ) {\r\n\r\n\t\t\t\t\tcachedMaterial = result.clone();\r\n\t\t\t\t\tmaterialsForVariant[ keyB ] = cachedMaterial;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tresult = cachedMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tresult.visible = material.visible;\r\n\t\t\tresult.wireframe = material.wireframe;\r\n\r\n\t\t\tif ( type === VSMShadowMap ) {\r\n\r\n\t\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tresult.clipShadows = material.clipShadows;\r\n\t\t\tresult.clippingPlanes = material.clippingPlanes;\r\n\t\t\tresult.clipIntersection = material.clipIntersection;\r\n\r\n\t\t\tresult.wireframeLinewidth = material.wireframeLinewidth;\r\n\t\t\tresult.linewidth = material.linewidth;\r\n\r\n\t\t\tif ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {\r\n\r\n\t\t\t\tresult.referencePosition.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\tresult.nearDistance = shadowCameraNear;\r\n\t\t\t\tresult.farDistance = shadowCameraFar;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObject( object, camera, shadowCamera, light, type ) {\r\n\r\n\t\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\t\tvar visible = object.layers.test( camera.layers );\r\n\r\n\t\t\tif ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {\r\n\r\n\t\t\t\tif ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {\r\n\r\n\t\t\t\t\tobject.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );\r\n\r\n\t\t\t\t\tvar geometry = _objects.update( object );\r\n\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\t\t\t\tfor ( var k = 0, kl = groups.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar group = groups[ k ];\r\n\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\r\n\r\n\t\t\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );\r\n\r\n\t\t\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else if ( material.visible ) {\r\n\r\n\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type );\r\n\r\n\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\trenderObject( children[ i ], camera, shadowCamera, light, type );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLState( gl, extensions, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tfunction ColorBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar color = new Vector4();\r\n\t\t\tvar currentColorMask = null;\r\n\t\t\tvar currentColorClear = new Vector4( 0, 0, 0, 0 );\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetMask: function ( colorMask ) {\r\n\r\n\t\t\t\t\tif ( currentColorMask !== colorMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.colorMask( colorMask, colorMask, colorMask, colorMask );\r\n\t\t\t\t\t\tcurrentColorMask = colorMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( r, g, b, a, premultipliedAlpha ) {\r\n\r\n\t\t\t\t\tif ( premultipliedAlpha === true ) {\r\n\r\n\t\t\t\t\t\tr *= a; g *= a; b *= a;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcolor.set( r, g, b, a );\r\n\r\n\t\t\t\t\tif ( currentColorClear.equals( color ) === false ) {\r\n\r\n\t\t\t\t\t\tgl.clearColor( r, g, b, a );\r\n\t\t\t\t\t\tcurrentColorClear.copy( color );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentColorMask = null;\r\n\t\t\t\t\tcurrentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction DepthBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar currentDepthMask = null;\r\n\t\t\tvar currentDepthFunc = null;\r\n\t\t\tvar currentDepthClear = null;\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetTest: function ( depthTest ) {\r\n\r\n\t\t\t\t\tif ( depthTest ) {\r\n\r\n\t\t\t\t\t\tenable( 2929 );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tdisable( 2929 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetMask: function ( depthMask ) {\r\n\r\n\t\t\t\t\tif ( currentDepthMask !== depthMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.depthMask( depthMask );\r\n\t\t\t\t\t\tcurrentDepthMask = depthMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetFunc: function ( depthFunc ) {\r\n\r\n\t\t\t\t\tif ( currentDepthFunc !== depthFunc ) {\r\n\r\n\t\t\t\t\t\tif ( depthFunc ) {\r\n\r\n\t\t\t\t\t\t\tswitch ( depthFunc ) {\r\n\r\n\t\t\t\t\t\t\t\tcase NeverDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 512 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase AlwaysDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 519 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase LessDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 513 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase LessEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase EqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 514 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase GreaterEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 518 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase GreaterDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 516 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase NotEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 517 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tcurrentDepthFunc = depthFunc;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( depth ) {\r\n\r\n\t\t\t\t\tif ( currentDepthClear !== depth ) {\r\n\r\n\t\t\t\t\t\tgl.clearDepth( depth );\r\n\t\t\t\t\t\tcurrentDepthClear = depth;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentDepthMask = null;\r\n\t\t\t\t\tcurrentDepthFunc = null;\r\n\t\t\t\t\tcurrentDepthClear = null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction StencilBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar currentStencilMask = null;\r\n\t\t\tvar currentStencilFunc = null;\r\n\t\t\tvar currentStencilRef = null;\r\n\t\t\tvar currentStencilFuncMask = null;\r\n\t\t\tvar currentStencilFail = null;\r\n\t\t\tvar currentStencilZFail = null;\r\n\t\t\tvar currentStencilZPass = null;\r\n\t\t\tvar currentStencilClear = null;\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetTest: function ( stencilTest ) {\r\n\r\n\t\t\t\t\tif ( ! locked ) {\r\n\r\n\t\t\t\t\t\tif ( stencilTest ) {\r\n\r\n\t\t\t\t\t\t\tenable( 2960 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tdisable( 2960 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetMask: function ( stencilMask ) {\r\n\r\n\t\t\t\t\tif ( currentStencilMask !== stencilMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.stencilMask( stencilMask );\r\n\t\t\t\t\t\tcurrentStencilMask = stencilMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetFunc: function ( stencilFunc, stencilRef, stencilMask ) {\r\n\r\n\t\t\t\t\tif ( currentStencilFunc !== stencilFunc ||\r\n\t\t\t\t\t currentStencilRef \t!== stencilRef \t||\r\n\t\t\t\t\t currentStencilFuncMask !== stencilMask ) {\r\n\r\n\t\t\t\t\t\tgl.stencilFunc( stencilFunc, stencilRef, stencilMask );\r\n\r\n\t\t\t\t\t\tcurrentStencilFunc = stencilFunc;\r\n\t\t\t\t\t\tcurrentStencilRef = stencilRef;\r\n\t\t\t\t\t\tcurrentStencilFuncMask = stencilMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetOp: function ( stencilFail, stencilZFail, stencilZPass ) {\r\n\r\n\t\t\t\t\tif ( currentStencilFail\t !== stencilFail \t||\r\n\t\t\t\t\t currentStencilZFail !== stencilZFail ||\r\n\t\t\t\t\t currentStencilZPass !== stencilZPass ) {\r\n\r\n\t\t\t\t\t\tgl.stencilOp( stencilFail, stencilZFail, stencilZPass );\r\n\r\n\t\t\t\t\t\tcurrentStencilFail = stencilFail;\r\n\t\t\t\t\t\tcurrentStencilZFail = stencilZFail;\r\n\t\t\t\t\t\tcurrentStencilZPass = stencilZPass;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( stencil ) {\r\n\r\n\t\t\t\t\tif ( currentStencilClear !== stencil ) {\r\n\r\n\t\t\t\t\t\tgl.clearStencil( stencil );\r\n\t\t\t\t\t\tcurrentStencilClear = stencil;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentStencilMask = null;\r\n\t\t\t\t\tcurrentStencilFunc = null;\r\n\t\t\t\t\tcurrentStencilRef = null;\r\n\t\t\t\t\tcurrentStencilFuncMask = null;\r\n\t\t\t\t\tcurrentStencilFail = null;\r\n\t\t\t\t\tcurrentStencilZFail = null;\r\n\t\t\t\t\tcurrentStencilZPass = null;\r\n\t\t\t\t\tcurrentStencilClear = null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar colorBuffer = new ColorBuffer();\r\n\t\tvar depthBuffer = new DepthBuffer();\r\n\t\tvar stencilBuffer = new StencilBuffer();\r\n\r\n\t\tvar maxVertexAttributes = gl.getParameter( 34921 );\r\n\t\tvar newAttributes = new Uint8Array( maxVertexAttributes );\r\n\t\tvar enabledAttributes = new Uint8Array( maxVertexAttributes );\r\n\t\tvar attributeDivisors = new Uint8Array( maxVertexAttributes );\r\n\r\n\t\tvar enabledCapabilities = {};\r\n\r\n\t\tvar currentProgram = null;\r\n\r\n\t\tvar currentBlendingEnabled = null;\r\n\t\tvar currentBlending = null;\r\n\t\tvar currentBlendEquation = null;\r\n\t\tvar currentBlendSrc = null;\r\n\t\tvar currentBlendDst = null;\r\n\t\tvar currentBlendEquationAlpha = null;\r\n\t\tvar currentBlendSrcAlpha = null;\r\n\t\tvar currentBlendDstAlpha = null;\r\n\t\tvar currentPremultipledAlpha = false;\r\n\r\n\t\tvar currentFlipSided = null;\r\n\t\tvar currentCullFace = null;\r\n\r\n\t\tvar currentLineWidth = null;\r\n\r\n\t\tvar currentPolygonOffsetFactor = null;\r\n\t\tvar currentPolygonOffsetUnits = null;\r\n\r\n\t\tvar maxTextures = gl.getParameter( 35661 );\r\n\r\n\t\tvar lineWidthAvailable = false;\r\n\t\tvar version = 0;\r\n\t\tvar glVersion = gl.getParameter( 7938 );\r\n\r\n\t\tif ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {\r\n\r\n\t\t\tversion = parseFloat( /^WebGL\\ ([0-9])/.exec( glVersion )[ 1 ] );\r\n\t\t\tlineWidthAvailable = ( version >= 1.0 );\r\n\r\n\t\t} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {\r\n\r\n\t\t\tversion = parseFloat( /^OpenGL\\ ES\\ ([0-9])/.exec( glVersion )[ 1 ] );\r\n\t\t\tlineWidthAvailable = ( version >= 2.0 );\r\n\r\n\t\t}\r\n\r\n\t\tvar currentTextureSlot = null;\r\n\t\tvar currentBoundTextures = {};\r\n\r\n\t\tvar currentScissor = new Vector4();\r\n\t\tvar currentViewport = new Vector4();\r\n\r\n\t\tfunction createTexture( type, target, count ) {\r\n\r\n\t\t\tvar data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.\r\n\t\t\tvar texture = gl.createTexture();\r\n\r\n\t\t\tgl.bindTexture( type, texture );\r\n\t\t\tgl.texParameteri( type, 10241, 9728 );\r\n\t\t\tgl.texParameteri( type, 10240, 9728 );\r\n\r\n\t\t\tfor ( var i = 0; i < count; i ++ ) {\r\n\r\n\t\t\t\tgl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t\tvar emptyTextures = {};\r\n\t\temptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );\r\n\t\temptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );\r\n\r\n\t\t// init\r\n\r\n\t\tcolorBuffer.setClear( 0, 0, 0, 1 );\r\n\t\tdepthBuffer.setClear( 1 );\r\n\t\tstencilBuffer.setClear( 0 );\r\n\r\n\t\tenable( 2929 );\r\n\t\tdepthBuffer.setFunc( LessEqualDepth );\r\n\r\n\t\tsetFlipSided( false );\r\n\t\tsetCullFace( CullFaceBack );\r\n\t\tenable( 2884 );\r\n\r\n\t\tsetBlending( NoBlending );\r\n\r\n\t\t//\r\n\r\n\t\tfunction initAttributes() {\r\n\r\n\t\t\tfor ( var i = 0, l = newAttributes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tnewAttributes[ i ] = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction enableAttribute( attribute ) {\r\n\r\n\t\t\tenableAttributeAndDivisor( attribute, 0 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction enableAttributeAndDivisor( attribute, meshPerAttribute ) {\r\n\r\n\t\t\tnewAttributes[ attribute ] = 1;\r\n\r\n\t\t\tif ( enabledAttributes[ attribute ] === 0 ) {\r\n\r\n\t\t\t\tgl.enableVertexAttribArray( attribute );\r\n\t\t\t\tenabledAttributes[ attribute ] = 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( attributeDivisors[ attribute ] !== meshPerAttribute ) {\r\n\r\n\t\t\t\tvar extension = isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t\t\textension[ isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );\r\n\t\t\t\tattributeDivisors[ attribute ] = meshPerAttribute;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction disableUnusedAttributes() {\r\n\r\n\t\t\tfor ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {\r\n\r\n\t\t\t\tif ( enabledAttributes[ i ] !== newAttributes[ i ] ) {\r\n\r\n\t\t\t\t\tgl.disableVertexAttribArray( i );\r\n\t\t\t\t\tenabledAttributes[ i ] = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction enable( id ) {\r\n\r\n\t\t\tif ( enabledCapabilities[ id ] !== true ) {\r\n\r\n\t\t\t\tgl.enable( id );\r\n\t\t\t\tenabledCapabilities[ id ] = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction disable( id ) {\r\n\r\n\t\t\tif ( enabledCapabilities[ id ] !== false ) {\r\n\r\n\t\t\t\tgl.disable( id );\r\n\t\t\t\tenabledCapabilities[ id ] = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction useProgram( program ) {\r\n\r\n\t\t\tif ( currentProgram !== program ) {\r\n\r\n\t\t\t\tgl.useProgram( program );\r\n\r\n\t\t\t\tcurrentProgram = program;\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t}\r\n\r\n\t\tvar equationToGL = {};\n\t\tequationToGL[ AddEquation ] = 32774;\n\t\tequationToGL[ SubtractEquation ] = 32778;\n\t\tequationToGL[ ReverseSubtractEquation ] = 32779;\r\n\r\n\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\tequationToGL[ MinEquation ] = 32775;\r\n\t\t\tequationToGL[ MaxEquation ] = 32776;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_blend_minmax' );\r\n\r\n\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\tequationToGL[ MinEquation ] = extension.MIN_EXT;\r\n\t\t\t\tequationToGL[ MaxEquation ] = extension.MAX_EXT;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar factorToGL = {};\n\t\tfactorToGL[ ZeroFactor ] = 0;\n\t\tfactorToGL[ OneFactor ] = 1;\n\t\tfactorToGL[ SrcColorFactor ] = 768;\n\t\tfactorToGL[ SrcAlphaFactor ] = 770;\n\t\tfactorToGL[ SrcAlphaSaturateFactor ] = 776;\n\t\tfactorToGL[ DstColorFactor ] = 774;\n\t\tfactorToGL[ DstAlphaFactor ] = 772;\n\t\tfactorToGL[ OneMinusSrcColorFactor ] = 769;\n\t\tfactorToGL[ OneMinusSrcAlphaFactor ] = 771;\n\t\tfactorToGL[ OneMinusDstColorFactor ] = 775;\n\t\tfactorToGL[ OneMinusDstAlphaFactor ] = 773;\r\n\r\n\t\tfunction setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {\r\n\r\n\t\t\tif ( blending === NoBlending ) {\r\n\r\n\t\t\t\tif ( currentBlendingEnabled ) {\r\n\r\n\t\t\t\t\tdisable( 3042 );\r\n\t\t\t\t\tcurrentBlendingEnabled = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! currentBlendingEnabled ) {\r\n\r\n\t\t\t\tenable( 3042 );\r\n\t\t\t\tcurrentBlendingEnabled = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( blending !== CustomBlending ) {\r\n\r\n\t\t\t\tif ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {\r\n\r\n\t\t\t\t\tif ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {\r\n\r\n\t\t\t\t\t\tgl.blendEquation( 32774 );\r\n\r\n\t\t\t\t\t\tcurrentBlendEquation = AddEquation;\r\n\t\t\t\t\t\tcurrentBlendEquationAlpha = AddEquation;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( premultipliedAlpha ) {\r\n\r\n\t\t\t\t\t\tswitch ( blending ) {\r\n\r\n\t\t\t\t\t\t\tcase NormalBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 1, 771, 1, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase AdditiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 1, 1 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase SubtractiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 0, 0, 769, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase MultiplyBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 0, 768, 0, 770 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tswitch ( blending ) {\r\n\r\n\t\t\t\t\t\t\tcase NormalBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 770, 771, 1, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase AdditiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 770, 1 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase SubtractiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 0, 769 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase MultiplyBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 0, 768 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcurrentBlendSrc = null;\r\n\t\t\t\t\tcurrentBlendDst = null;\r\n\t\t\t\t\tcurrentBlendSrcAlpha = null;\r\n\t\t\t\t\tcurrentBlendDstAlpha = null;\r\n\r\n\t\t\t\t\tcurrentBlending = blending;\r\n\t\t\t\t\tcurrentPremultipledAlpha = premultipliedAlpha;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// custom blending\r\n\r\n\t\t\tblendEquationAlpha = blendEquationAlpha || blendEquation;\r\n\t\t\tblendSrcAlpha = blendSrcAlpha || blendSrc;\r\n\t\t\tblendDstAlpha = blendDstAlpha || blendDst;\r\n\r\n\t\t\tif ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {\r\n\r\n\t\t\t\tgl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );\r\n\r\n\t\t\t\tcurrentBlendEquation = blendEquation;\r\n\t\t\t\tcurrentBlendEquationAlpha = blendEquationAlpha;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {\r\n\r\n\t\t\t\tgl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );\r\n\r\n\t\t\t\tcurrentBlendSrc = blendSrc;\r\n\t\t\t\tcurrentBlendDst = blendDst;\r\n\t\t\t\tcurrentBlendSrcAlpha = blendSrcAlpha;\r\n\t\t\t\tcurrentBlendDstAlpha = blendDstAlpha;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcurrentBlending = blending;\r\n\t\t\tcurrentPremultipledAlpha = null;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setMaterial( material, frontFaceCW ) {\r\n\r\n\t\t\tmaterial.side === DoubleSide\r\n\t\t\t\t? disable( 2884 )\r\n\t\t\t\t: enable( 2884 );\r\n\r\n\t\t\tvar flipSided = ( material.side === BackSide );\r\n\t\t\tif ( frontFaceCW ) { flipSided = ! flipSided; }\r\n\r\n\t\t\tsetFlipSided( flipSided );\r\n\r\n\t\t\t( material.blending === NormalBlending && material.transparent === false )\r\n\t\t\t\t? setBlending( NoBlending )\r\n\t\t\t\t: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );\r\n\r\n\t\t\tdepthBuffer.setFunc( material.depthFunc );\r\n\t\t\tdepthBuffer.setTest( material.depthTest );\r\n\t\t\tdepthBuffer.setMask( material.depthWrite );\r\n\t\t\tcolorBuffer.setMask( material.colorWrite );\r\n\r\n\t\t\tvar stencilWrite = material.stencilWrite;\r\n\t\t\tstencilBuffer.setTest( stencilWrite );\r\n\t\t\tif ( stencilWrite ) {\r\n\r\n\t\t\t\tstencilBuffer.setMask( material.stencilWriteMask );\r\n\t\t\t\tstencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );\r\n\t\t\t\tstencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction setFlipSided( flipSided ) {\r\n\r\n\t\t\tif ( currentFlipSided !== flipSided ) {\r\n\r\n\t\t\t\tif ( flipSided ) {\r\n\r\n\t\t\t\t\tgl.frontFace( 2304 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tgl.frontFace( 2305 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcurrentFlipSided = flipSided;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setCullFace( cullFace ) {\r\n\r\n\t\t\tif ( cullFace !== CullFaceNone ) {\r\n\r\n\t\t\t\tenable( 2884 );\r\n\r\n\t\t\t\tif ( cullFace !== currentCullFace ) {\r\n\r\n\t\t\t\t\tif ( cullFace === CullFaceBack ) {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1029 );\r\n\r\n\t\t\t\t\t} else if ( cullFace === CullFaceFront ) {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1028 );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1032 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 2884 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcurrentCullFace = cullFace;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setLineWidth( width ) {\r\n\r\n\t\t\tif ( width !== currentLineWidth ) {\r\n\r\n\t\t\t\tif ( lineWidthAvailable ) { gl.lineWidth( width ); }\r\n\r\n\t\t\t\tcurrentLineWidth = width;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setPolygonOffset( polygonOffset, factor, units ) {\r\n\r\n\t\t\tif ( polygonOffset ) {\r\n\r\n\t\t\t\tenable( 32823 );\r\n\r\n\t\t\t\tif ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {\r\n\r\n\t\t\t\t\tgl.polygonOffset( factor, units );\r\n\r\n\t\t\t\t\tcurrentPolygonOffsetFactor = factor;\r\n\t\t\t\t\tcurrentPolygonOffsetUnits = units;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 32823 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setScissorTest( scissorTest ) {\r\n\r\n\t\t\tif ( scissorTest ) {\r\n\r\n\t\t\t\tenable( 3089 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 3089 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// texture\r\n\r\n\t\tfunction activeTexture( webglSlot ) {\r\n\r\n\t\t\tif ( webglSlot === undefined ) { webglSlot = 33984 + maxTextures - 1; }\r\n\r\n\t\t\tif ( currentTextureSlot !== webglSlot ) {\r\n\r\n\t\t\t\tgl.activeTexture( webglSlot );\r\n\t\t\t\tcurrentTextureSlot = webglSlot;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction bindTexture( webglType, webglTexture ) {\r\n\r\n\t\t\tif ( currentTextureSlot === null ) {\r\n\r\n\t\t\t\tactiveTexture();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\r\n\r\n\t\t\tif ( boundTexture === undefined ) {\r\n\r\n\t\t\t\tboundTexture = { type: undefined, texture: undefined };\r\n\t\t\t\tcurrentBoundTextures[ currentTextureSlot ] = boundTexture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {\r\n\r\n\t\t\t\tgl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );\r\n\r\n\t\t\t\tboundTexture.type = webglType;\r\n\t\t\t\tboundTexture.texture = webglTexture;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction unbindTexture() {\r\n\r\n\t\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\r\n\r\n\t\t\tif ( boundTexture !== undefined && boundTexture.type !== undefined ) {\r\n\r\n\t\t\t\tgl.bindTexture( boundTexture.type, null );\r\n\r\n\t\t\t\tboundTexture.type = undefined;\r\n\t\t\t\tboundTexture.texture = undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction compressedTexImage2D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.compressedTexImage2D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction texImage2D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.texImage2D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction texImage3D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.texImage3D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction scissor( scissor ) {\r\n\r\n\t\t\tif ( currentScissor.equals( scissor ) === false ) {\r\n\r\n\t\t\t\tgl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );\r\n\t\t\t\tcurrentScissor.copy( scissor );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction viewport( viewport ) {\r\n\r\n\t\t\tif ( currentViewport.equals( viewport ) === false ) {\r\n\r\n\t\t\t\tgl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );\r\n\t\t\t\tcurrentViewport.copy( viewport );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction reset() {\r\n\r\n\t\t\tfor ( var i = 0; i < enabledAttributes.length; i ++ ) {\r\n\r\n\t\t\t\tif ( enabledAttributes[ i ] === 1 ) {\r\n\r\n\t\t\t\t\tgl.disableVertexAttribArray( i );\r\n\t\t\t\t\tenabledAttributes[ i ] = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tenabledCapabilities = {};\r\n\r\n\t\t\tcurrentTextureSlot = null;\r\n\t\t\tcurrentBoundTextures = {};\r\n\r\n\t\t\tcurrentProgram = null;\r\n\r\n\t\t\tcurrentBlending = null;\r\n\r\n\t\t\tcurrentFlipSided = null;\r\n\t\t\tcurrentCullFace = null;\r\n\r\n\t\t\tcolorBuffer.reset();\r\n\t\t\tdepthBuffer.reset();\r\n\t\t\tstencilBuffer.reset();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tbuffers: {\r\n\t\t\t\tcolor: colorBuffer,\r\n\t\t\t\tdepth: depthBuffer,\r\n\t\t\t\tstencil: stencilBuffer\r\n\t\t\t},\r\n\r\n\t\t\tinitAttributes: initAttributes,\r\n\t\t\tenableAttribute: enableAttribute,\r\n\t\t\tenableAttributeAndDivisor: enableAttributeAndDivisor,\r\n\t\t\tdisableUnusedAttributes: disableUnusedAttributes,\r\n\t\t\tenable: enable,\r\n\t\t\tdisable: disable,\r\n\r\n\t\t\tuseProgram: useProgram,\r\n\r\n\t\t\tsetBlending: setBlending,\r\n\t\t\tsetMaterial: setMaterial,\r\n\r\n\t\t\tsetFlipSided: setFlipSided,\r\n\t\t\tsetCullFace: setCullFace,\r\n\r\n\t\t\tsetLineWidth: setLineWidth,\r\n\t\t\tsetPolygonOffset: setPolygonOffset,\r\n\r\n\t\t\tsetScissorTest: setScissorTest,\r\n\r\n\t\t\tactiveTexture: activeTexture,\r\n\t\t\tbindTexture: bindTexture,\r\n\t\t\tunbindTexture: unbindTexture,\r\n\t\t\tcompressedTexImage2D: compressedTexImage2D,\r\n\t\t\ttexImage2D: texImage2D,\r\n\t\t\ttexImage3D: texImage3D,\r\n\r\n\t\t\tscissor: scissor,\r\n\t\t\tviewport: viewport,\r\n\r\n\t\t\treset: reset\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\t\tvar maxTextures = capabilities.maxTextures;\r\n\t\tvar maxCubemapSize = capabilities.maxCubemapSize;\r\n\t\tvar maxTextureSize = capabilities.maxTextureSize;\r\n\t\tvar maxSamples = capabilities.maxSamples;\r\n\r\n\t\tvar _videoTextures = new WeakMap();\r\n\t\tvar _canvas;\r\n\r\n\t\t// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,\r\n\t\t// also OffscreenCanvas.getContext(\"webgl\"), but not OffscreenCanvas.getContext(\"2d\")!\r\n\t\t// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).\r\n\r\n\t\tvar useOffscreenCanvas = false;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tuseOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'\r\n\t\t\t\t&& ( new OffscreenCanvas( 1, 1 ).getContext( \"2d\" ) ) !== null;\r\n\r\n\t\t} catch ( err ) {\r\n\r\n\t\t\t// Ignore any errors\r\n\r\n\t\t}\r\n\r\n\t\tfunction createCanvas( width, height ) {\r\n\r\n\t\t\t// Use OffscreenCanvas when available. Specially needed in web workers\r\n\r\n\t\t\treturn useOffscreenCanvas ?\r\n\t\t\t\tnew OffscreenCanvas( width, height ) :\r\n\t\t\t\tdocument.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\r\n\r\n\t\t}\r\n\r\n\t\tfunction resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {\r\n\r\n\t\t\tvar scale = 1;\r\n\r\n\t\t\t// handle case if texture exceeds max size\r\n\r\n\t\t\tif ( image.width > maxSize || image.height > maxSize ) {\r\n\r\n\t\t\t\tscale = maxSize / Math.max( image.width, image.height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// only perform resize if necessary\r\n\r\n\t\t\tif ( scale < 1 || needsPowerOfTwo === true ) {\r\n\r\n\t\t\t\t// only perform resize for certain image types\r\n\r\n\t\t\t\tif ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||\r\n\t\t\t\t\t( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||\r\n\t\t\t\t\t( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {\r\n\r\n\t\t\t\t\tvar floor = needsPowerOfTwo ? _Math.floorPowerOfTwo : Math.floor;\r\n\r\n\t\t\t\t\tvar width = floor( scale * image.width );\r\n\t\t\t\t\tvar height = floor( scale * image.height );\r\n\r\n\t\t\t\t\tif ( _canvas === undefined ) { _canvas = createCanvas( width, height ); }\r\n\r\n\t\t\t\t\t// cube textures can't reuse the same canvas\r\n\r\n\t\t\t\t\tvar canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;\r\n\r\n\t\t\t\t\tcanvas.width = width;\r\n\t\t\t\t\tcanvas.height = height;\r\n\r\n\t\t\t\t\tvar context = canvas.getContext( '2d' );\r\n\t\t\t\t\tcontext.drawImage( image, 0, 0, width, height );\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );\r\n\r\n\t\t\t\t\treturn canvas;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tif ( 'data' in image ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn image;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn image;\r\n\r\n\t\t}\r\n\r\n\t\tfunction isPowerOfTwo( image ) {\r\n\r\n\t\t\treturn _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );\r\n\r\n\t\t}\r\n\r\n\t\tfunction textureNeedsPowerOfTwo( texture ) {\r\n\r\n\t\t\tif ( isWebGL2 ) { return false; }\r\n\r\n\t\t\treturn ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||\r\n\t\t\t\t( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );\r\n\r\n\t\t}\r\n\r\n\t\tfunction textureNeedsGenerateMipmaps( texture, supportsMips ) {\r\n\r\n\t\t\treturn texture.generateMipmaps && supportsMips &&\r\n\t\t\t\ttexture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateMipmap( target, texture, width, height ) {\r\n\r\n\t\t\t_gl.generateMipmap( target );\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\t// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11\r\n\t\t\ttextureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getInternalFormat( glFormat, glType ) {\r\n\r\n\t\t\tif ( isWebGL2 === false ) { return glFormat; }\r\n\r\n\t\t\tvar internalFormat = glFormat;\r\n\r\n\t\t\tif ( glFormat === 6403 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 33326; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 33325; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 33321; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( glFormat === 6407 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 34837; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 34843; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 32849; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( glFormat === 6408 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 34836; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 34842; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 32856; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( internalFormat === 33325 || internalFormat === 33326 ||\r\n\t\t\t\tinternalFormat === 34842 || internalFormat === 34836 ) {\r\n\r\n\t\t\t\textensions.get( 'EXT_color_buffer_float' );\r\n\r\n\t\t\t} else if ( internalFormat === 34843 || internalFormat === 34837 ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn internalFormat;\r\n\r\n\t\t}\r\n\r\n\t\t// Fallback filters for non-power-of-2 textures\r\n\r\n\t\tfunction filterFallback( f ) {\r\n\r\n\t\t\tif ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {\r\n\r\n\t\t\t\treturn 9728;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 9729;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction onTextureDispose( event ) {\r\n\r\n\t\t\tvar texture = event.target;\r\n\r\n\t\t\ttexture.removeEventListener( 'dispose', onTextureDispose );\r\n\r\n\t\t\tdeallocateTexture( texture );\r\n\r\n\t\t\tif ( texture.isVideoTexture ) {\r\n\r\n\t\t\t\t_videoTextures.delete( texture );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tinfo.memory.textures --;\r\n\r\n\t\t}\r\n\r\n\t\tfunction onRenderTargetDispose( event ) {\r\n\r\n\t\t\tvar renderTarget = event.target;\r\n\r\n\t\t\trenderTarget.removeEventListener( 'dispose', onRenderTargetDispose );\r\n\r\n\t\t\tdeallocateRenderTarget( renderTarget );\r\n\r\n\t\t\tinfo.memory.textures --;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction deallocateTexture( texture ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( textureProperties.__webglInit === undefined ) { return; }\r\n\r\n\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\r\n\r\n\t\t\tproperties.remove( texture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction deallocateRenderTarget( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\r\n\t\t\tif ( ! renderTarget ) { return; }\r\n\r\n\t\t\tif ( textureProperties.__webglTexture !== undefined ) {\r\n\r\n\t\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.depthTexture ) {\r\n\r\n\t\t\t\trenderTarget.depthTexture.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );\r\n\t\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );\r\n\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.isWebGLMultiviewRenderTarget ) {\r\n\r\n\t\t\t\t_gl.deleteTexture( renderTargetProperties.__webglColorTexture );\r\n\t\t\t\t_gl.deleteTexture( renderTargetProperties.__webglDepthStencilTexture );\r\n\r\n\t\t\t\tinfo.memory.textures -= 2;\r\n\r\n\t\t\t\tfor ( var i = 0, il = renderTargetProperties.__webglViewFramebuffers.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglViewFramebuffers[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tproperties.remove( renderTarget.texture );\r\n\t\t\tproperties.remove( renderTarget );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar textureUnits = 0;\r\n\r\n\t\tfunction resetTextureUnits() {\r\n\r\n\t\t\ttextureUnits = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction allocateTextureUnit() {\r\n\r\n\t\t\tvar textureUnit = textureUnits;\r\n\r\n\t\t\tif ( textureUnit >= maxTextures ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttextureUnits += 1;\r\n\r\n\t\t\treturn textureUnit;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction setTexture2D( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.isVideoTexture ) { updateVideoTexture( texture ); }\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tvar image = texture.image;\r\n\r\n\t\t\t\tif ( image === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );\r\n\r\n\t\t\t\t} else if ( image.complete === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 3553, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTexture2DArray( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 35866, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTexture3D( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 32879, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTextureCube( texture, slot ) {\r\n\r\n\t\t\tif ( texture.image.length !== 6 ) { return; }\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tinitTexture( textureProperties, texture );\r\n\r\n\t\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\r\n\t\t\t\t_gl.pixelStorei( 37440, texture.flipY );\r\n\r\n\t\t\t\tvar isCompressed = ( texture && texture.isCompressedTexture );\r\n\t\t\t\tvar isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );\r\n\r\n\t\t\t\tvar cubeImage = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\tif ( ! isCompressed && ! isDataTexture ) {\r\n\r\n\t\t\t\t\t\tcubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tcubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar image = cubeImage[ 0 ],\r\n\t\t\t\t\tsupportsMips = isPowerOfTwo( image ) || isWebGL2,\r\n\t\t\t\t\tglFormat = utils.convert( texture.format ),\r\n\t\t\t\t\tglType = utils.convert( texture.type ),\r\n\t\t\t\t\tglInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\t\tsetTextureParameters( 34067, texture, supportsMips );\r\n\r\n\t\t\t\tvar mipmaps;\r\n\r\n\t\t\t\tif ( isCompressed ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmaps = cubeImage[ i ].mipmaps;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( glFormat !== null ) {\r\n\r\n\t\t\t\t\t\t\t\t\tstate.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\r\n\r\n\t\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tmipmaps = texture.mipmaps;\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\tif ( isDataTexture ) {\r\n\r\n\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\t\t\t\t\t\t\t\tvar mipmapImage = mipmap.image[ i ].image;\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\t// We assume images for cube map have the same size.\r\n\t\t\t\t\tgenerateMipmap( 34067, texture, image.width, image.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextureProperties.__version = texture.version;\r\n\r\n\t\t\t\tif ( texture.onUpdate ) { texture.onUpdate( texture ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTextureCubeDynamic( texture, slot ) {\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 34067, properties.get( texture ).__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tvar wrappingToGL = {};\n\t\twrappingToGL[ RepeatWrapping ] = 10497;\n\t\twrappingToGL[ ClampToEdgeWrapping ] = 33071;\n\t\twrappingToGL[ MirroredRepeatWrapping ] = 33648;\r\n\r\n\t\tvar filterToGL = {};\n\t\tfilterToGL[ NearestFilter ] = 9728;\n\t\tfilterToGL[ NearestMipmapNearestFilter ] = 9984;\n\t\tfilterToGL[ NearestMipmapLinearFilter ] = 9986;\n\t\tfilterToGL[ LinearFilter ] = 9729;\n\t\tfilterToGL[ LinearMipmapNearestFilter ] = 9985;\n\t\tfilterToGL[ LinearMipmapLinearFilter ] = 9987;\r\n\r\n\t\tfunction setTextureParameters( textureType, texture, supportsMips ) {\r\n\r\n\t\t\tif ( supportsMips ) {\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );\r\n\t\t\t\t_gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );\r\n\r\n\t\t\t\tif ( textureType === 32879 || textureType === 35866 ) {\r\n\r\n\t\t\t\t\t_gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );\r\n\t\t\t\t_gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10242, 33071 );\r\n\t\t\t\t_gl.texParameteri( textureType, 10243, 33071 );\r\n\r\n\t\t\t\tif ( textureType === 32879 || textureType === 35866 ) {\r\n\r\n\t\t\t\t\t_gl.texParameteri( textureType, 32882, 33071 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );\r\n\t\t\t\t_gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );\r\n\r\n\t\t\t\tif ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\r\n\r\n\t\t\tif ( extension ) {\r\n\r\n\t\t\t\tif ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) { return; }\r\n\t\t\t\tif ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) { return; }\r\n\r\n\t\t\t\tif ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {\r\n\r\n\t\t\t\t\t_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );\r\n\t\t\t\t\tproperties.get( texture ).__currentAnisotropy = texture.anisotropy;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction initTexture( textureProperties, texture ) {\r\n\r\n\t\t\tif ( textureProperties.__webglInit === undefined ) {\r\n\r\n\t\t\t\ttextureProperties.__webglInit = true;\r\n\r\n\t\t\t\ttexture.addEventListener( 'dispose', onTextureDispose );\r\n\r\n\t\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\r\n\r\n\t\t\t\tinfo.memory.textures ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction uploadTexture( textureProperties, texture, slot ) {\r\n\r\n\t\t\tvar textureType = 3553;\r\n\r\n\t\t\tif ( texture.isDataTexture2DArray ) { textureType = 35866; }\r\n\t\t\tif ( texture.isDataTexture3D ) { textureType = 32879; }\r\n\r\n\t\t\tinitTexture( textureProperties, texture );\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( textureType, textureProperties.__webglTexture );\r\n\r\n\t\t\t_gl.pixelStorei( 37440, texture.flipY );\r\n\t\t\t_gl.pixelStorei( 37441, texture.premultiplyAlpha );\r\n\t\t\t_gl.pixelStorei( 3317, texture.unpackAlignment );\r\n\r\n\t\t\tvar needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;\r\n\t\t\tvar image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );\r\n\r\n\t\t\tvar supportsMips = isPowerOfTwo( image ) || isWebGL2,\r\n\t\t\t\tglFormat = utils.convert( texture.format ),\r\n\t\t\t\tglType = utils.convert( texture.type ),\r\n\t\t\t\tglInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\tsetTextureParameters( textureType, texture, supportsMips );\r\n\r\n\t\t\tvar mipmap, mipmaps = texture.mipmaps;\r\n\r\n\t\t\tif ( texture.isDepthTexture ) {\r\n\r\n\t\t\t\t// populate depth texture with dummy data\r\n\r\n\t\t\t\tglInternalFormat = 6402;\r\n\r\n\t\t\t\tif ( texture.type === FloatType ) {\r\n\r\n\t\t\t\t\tif ( isWebGL2 === false ) { throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); }\r\n\t\t\t\t\tglInternalFormat = 36012;\r\n\r\n\t\t\t\t} else if ( isWebGL2 ) {\r\n\r\n\t\t\t\t\t// WebGL 2.0 requires signed internalformat for glTexImage2D\r\n\t\t\t\t\tglInternalFormat = 33189;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texture.format === DepthFormat && glInternalFormat === 6402 ) {\r\n\r\n\t\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\r\n\t\t\t\t\t// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT\r\n\t\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\t\tif ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );\r\n\r\n\t\t\t\t\t\ttexture.type = UnsignedShortType;\r\n\t\t\t\t\t\tglType = utils.convert( texture.type );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Depth stencil textures need the DEPTH_STENCIL internal format\r\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\tif ( texture.format === DepthStencilFormat ) {\r\n\r\n\t\t\t\t\tglInternalFormat = 34041;\r\n\r\n\t\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\r\n\t\t\t\t\t// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.\r\n\t\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\t\tif ( texture.type !== UnsignedInt248Type ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );\r\n\r\n\t\t\t\t\t\ttexture.type = UnsignedInt248Type;\r\n\t\t\t\t\t\tglType = utils.convert( texture.type );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );\r\n\r\n\t\t\t} else if ( texture.isDataTexture ) {\r\n\r\n\t\t\t\t// use manually created mipmaps if available\r\n\t\t\t\t// if there are no manual mipmaps\r\n\t\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\r\n\r\n\t\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.generateMipmaps = false;\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( texture.isCompressedTexture ) {\r\n\r\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\r\n\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\r\n\r\n\t\t\t\t\t\tif ( glFormat !== null ) {\r\n\r\n\t\t\t\t\t\t\tstate.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t} else if ( texture.isDataTexture2DArray ) {\r\n\r\n\t\t\t\tstate.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\r\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t} else if ( texture.isDataTexture3D ) {\r\n\r\n\t\t\t\tstate.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\r\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// regular Texture (image, video, canvas)\r\n\r\n\t\t\t\t// use manually created mipmaps if available\r\n\t\t\t\t// if there are no manual mipmaps\r\n\t\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\r\n\r\n\t\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.generateMipmaps = false;\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\tgenerateMipmap( 3553, texture, image.width, image.height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttextureProperties.__version = texture.version;\r\n\r\n\t\t\tif ( texture.onUpdate ) { texture.onUpdate( texture ); }\r\n\r\n\t\t}\r\n\r\n\t\t// Render targets\r\n\r\n\t\t// Setup storage for target texture and bind it to correct framebuffer\r\n\t\tfunction setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {\r\n\r\n\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\t\t\tstate.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );\r\n\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\t\t\t_gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );\r\n\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Setup storage for internal depth/stencil buffers and bind to correct framebuffer\r\n\t\tfunction setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {\r\n\r\n\t\t\t_gl.bindRenderbuffer( 36161, renderbuffer );\r\n\r\n\t\t\tif ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, 33189, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, 33189, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );\r\n\r\n\t\t\t} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t_gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_gl.bindRenderbuffer( 36161, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Setup resources for a Depth Texture for a FBO (needs an extension)\r\n\t\tfunction setupDepthTexture( framebuffer, renderTarget ) {\r\n\r\n\t\t\tvar isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );\r\n\t\t\tif ( isCube ) { throw new Error( 'Depth Texture with cube render targets is not supported' ); }\r\n\r\n\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\r\n\t\t\tif ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {\r\n\r\n\t\t\t\tthrow new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// upload an empty depth texture with framebuffer size\r\n\t\t\tif ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||\r\n\t\t\t\t\trenderTarget.depthTexture.image.width !== renderTarget.width ||\r\n\t\t\t\t\trenderTarget.depthTexture.image.height !== renderTarget.height ) {\r\n\r\n\t\t\t\trenderTarget.depthTexture.image.width = renderTarget.width;\r\n\t\t\t\trenderTarget.depthTexture.image.height = renderTarget.height;\r\n\t\t\t\trenderTarget.depthTexture.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetTexture2D( renderTarget.depthTexture, 0 );\r\n\r\n\t\t\tvar webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;\r\n\r\n\t\t\tif ( renderTarget.depthTexture.format === DepthFormat ) {\r\n\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );\r\n\r\n\t\t\t} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {\r\n\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthrow new Error( 'Unknown depthTexture format' );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Setup GL resources for a non-texture depth buffer\r\n\t\tfunction setupDepthRenderbuffer( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\r\n\t\t\tvar isCube = ( renderTarget.isWebGLRenderTargetCube === true );\r\n\r\n\t\t\tif ( renderTarget.depthTexture ) {\r\n\r\n\t\t\t\tif ( isCube ) { throw new Error( 'target.depthTexture not supported in Cube render targets' ); }\r\n\r\n\t\t\t\tsetupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );\r\n\t\t\t\t\t\trenderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();\r\n\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );\r\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();\r\n\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Set up GL resources for the render target\r\n\t\tfunction setupRenderTarget( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\r\n\t\t\trenderTarget.addEventListener( 'dispose', onRenderTargetDispose );\r\n\r\n\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\r\n\r\n\t\t\tinfo.memory.textures ++;\r\n\r\n\t\t\tvar isCube = ( renderTarget.isWebGLRenderTargetCube === true );\r\n\t\t\tvar isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );\r\n\t\t\tvar isMultiview = ( renderTarget.isWebGLMultiviewRenderTarget === true );\r\n\t\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\r\n\r\n\t\t\t// Setup framebuffer\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\trenderTargetProperties.__webglFramebuffer = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\t\t\trenderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();\r\n\t\t\t\t\t\trenderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();\r\n\r\n\t\t\t\t\t\t_gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );\r\n\t\t\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\t\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\t\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\t\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );\r\n\t\t\t\t\t\t_gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );\r\n\t\t\t\t\t\t_gl.bindRenderbuffer( 36161, null );\r\n\r\n\t\t\t\t\t\tif ( renderTarget.depthBuffer ) {\r\n\r\n\t\t\t\t\t\t\trenderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();\r\n\t\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( isMultiview ) {\r\n\r\n\t\t\t\t\tvar width = renderTarget.width;\r\n\t\t\t\t\tvar height = renderTarget.height;\r\n\t\t\t\t\tvar numViews = renderTarget.numViews;\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );\r\n\r\n\t\t\t\t\tvar ext = extensions.get( 'OVR_multiview2' );\r\n\r\n\t\t\t\t\tinfo.memory.textures += 2;\r\n\r\n\t\t\t\t\tvar colorTexture = _gl.createTexture();\r\n\t\t\t\t\t_gl.bindTexture( 35866, colorTexture );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10240, 9728 );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10241, 9728 );\r\n\t\t\t\t\t_gl.texImage3D( 35866, 0, 32856, width, height, numViews, 0, 6408, 5121, null );\r\n\t\t\t\t\text.framebufferTextureMultiviewOVR( 36160, 36064, colorTexture, 0, 0, numViews );\r\n\r\n\t\t\t\t\tvar depthStencilTexture = _gl.createTexture();\r\n\t\t\t\t\t_gl.bindTexture( 35866, depthStencilTexture );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10240, 9728 );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10241, 9728 );\r\n\t\t\t\t\t_gl.texImage3D( 35866, 0, 35056, width, height, numViews, 0, 34041, 34042, null );\r\n\t\t\t\t\text.framebufferTextureMultiviewOVR( 36160, 33306, depthStencilTexture, 0, 0, numViews );\r\n\r\n\t\t\t\t\tvar viewFramebuffers = new Array( numViews );\r\n\t\t\t\t\tfor ( var i = 0; i < numViews; ++ i ) {\r\n\r\n\t\t\t\t\t\tviewFramebuffers[ i ] = _gl.createFramebuffer();\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, viewFramebuffers[ i ] );\r\n\t\t\t\t\t\t_gl.framebufferTextureLayer( 36160, 36064, colorTexture, 0, i );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglColorTexture = colorTexture;\r\n\t\t\t\t\trenderTargetProperties.__webglDepthStencilTexture = depthStencilTexture;\r\n\t\t\t\t\trenderTargetProperties.__webglViewFramebuffers = viewFramebuffers;\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\t\t\t\t\t_gl.bindTexture( 35866, null );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Setup color buffer\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\t\t\t\tsetTextureParameters( 34067, renderTarget.texture, supportsMips );\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\tgenerateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.bindTexture( 34067, null );\r\n\r\n\t\t\t} else if ( ! isMultiview ) {\r\n\r\n\t\t\t\tstate.bindTexture( 3553, textureProperties.__webglTexture );\r\n\t\t\t\tsetTextureParameters( 3553, renderTarget.texture, supportsMips );\r\n\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\tgenerateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.bindTexture( 3553, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Setup depth and stencil buffers\r\n\r\n\t\t\tif ( renderTarget.depthBuffer ) {\r\n\r\n\t\t\t\tsetupDepthRenderbuffer( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateRenderTargetMipmap( renderTarget ) {\r\n\r\n\t\t\tvar texture = renderTarget.texture;\r\n\t\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\r\n\r\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\tvar target = renderTarget.isWebGLRenderTargetCube ? 34067 : 3553;\r\n\t\t\t\tvar webglTexture = properties.get( texture ).__webglTexture;\r\n\r\n\t\t\t\tstate.bindTexture( target, webglTexture );\r\n\t\t\t\tgenerateMipmap( target, texture, renderTarget.width, renderTarget.height );\r\n\t\t\t\tstate.bindTexture( target, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateMultisampleRenderTarget( renderTarget ) {\r\n\r\n\t\t\tif ( renderTarget.isWebGLMultisampleRenderTarget ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );\r\n\t\t\t\t\t_gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );\r\n\r\n\t\t\t\t\tvar width = renderTarget.width;\r\n\t\t\t\t\tvar height = renderTarget.height;\r\n\t\t\t\t\tvar mask = 16384;\r\n\r\n\t\t\t\t\tif ( renderTarget.depthBuffer ) { mask |= 256; }\r\n\t\t\t\t\tif ( renderTarget.stencilBuffer ) { mask |= 1024; }\r\n\r\n\t\t\t\t\t_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction getRenderTargetSamples( renderTarget ) {\r\n\r\n\t\t\treturn ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?\r\n\t\t\t\tMath.min( maxSamples, renderTarget.samples ) : 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateVideoTexture( texture ) {\r\n\r\n\t\t\tvar frame = info.render.frame;\r\n\r\n\t\t\t// Check the last frame we updated the VideoTexture\r\n\r\n\t\t\tif ( _videoTextures.get( texture ) !== frame ) {\r\n\r\n\t\t\t\t_videoTextures.set( texture, frame );\r\n\t\t\t\ttexture.update();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// backwards compatibility\r\n\r\n\t\tvar warnedTexture2D = false;\r\n\t\tvar warnedTextureCube = false;\r\n\r\n\t\tfunction safeSetTexture2D( texture, slot ) {\r\n\r\n\t\t\tif ( texture && texture.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\tif ( warnedTexture2D === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\twarnedTexture2D = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetTexture2D( texture, slot );\r\n\r\n\t\t}\r\n\r\n\t\tfunction safeSetTextureCube( texture, slot ) {\r\n\r\n\t\t\tif ( texture && texture.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\tif ( warnedTextureCube === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\twarnedTextureCube = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture\r\n\t\t\t// TODO: unify these code paths\r\n\t\t\tif ( ( texture && texture.isCubeTexture ) ||\r\n\t\t\t\t( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {\r\n\r\n\t\t\t\t// CompressedTexture can have Array in image :/\r\n\r\n\t\t\t\t// this function alone should take care of cube textures\r\n\t\t\t\tsetTextureCube( texture, slot );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// assumed: texture property of THREE.WebGLRenderTargetCube\r\n\t\t\t\tsetTextureCubeDynamic( texture, slot );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.allocateTextureUnit = allocateTextureUnit;\r\n\t\tthis.resetTextureUnits = resetTextureUnits;\r\n\r\n\t\tthis.setTexture2D = setTexture2D;\r\n\t\tthis.setTexture2DArray = setTexture2DArray;\r\n\t\tthis.setTexture3D = setTexture3D;\r\n\t\tthis.setTextureCube = setTextureCube;\r\n\t\tthis.setTextureCubeDynamic = setTextureCubeDynamic;\r\n\t\tthis.setupRenderTarget = setupRenderTarget;\r\n\t\tthis.updateRenderTargetMipmap = updateRenderTargetMipmap;\r\n\t\tthis.updateMultisampleRenderTarget = updateMultisampleRenderTarget;\r\n\r\n\t\tthis.safeSetTexture2D = safeSetTexture2D;\r\n\t\tthis.safeSetTextureCube = safeSetTextureCube;\r\n\r\n\t}\n\n\t/**\r\n\t * @author thespite / http://www.twitter.com/thespite\r\n\t */\r\n\r\n\tfunction WebGLUtils( gl, extensions, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tfunction convert( p ) {\r\n\r\n\t\t\tvar extension;\r\n\r\n\t\t\tif ( p === UnsignedByteType ) { return 5121; }\r\n\t\t\tif ( p === UnsignedShort4444Type ) { return 32819; }\r\n\t\t\tif ( p === UnsignedShort5551Type ) { return 32820; }\r\n\t\t\tif ( p === UnsignedShort565Type ) { return 33635; }\r\n\r\n\t\t\tif ( p === ByteType ) { return 5120; }\r\n\t\t\tif ( p === ShortType ) { return 5122; }\r\n\t\t\tif ( p === UnsignedShortType ) { return 5123; }\r\n\t\t\tif ( p === IntType ) { return 5124; }\r\n\t\t\tif ( p === UnsignedIntType ) { return 5125; }\r\n\t\t\tif ( p === FloatType ) { return 5126; }\r\n\r\n\t\t\tif ( p === HalfFloatType ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) { return 5131; }\r\n\r\n\t\t\t\textension = extensions.get( 'OES_texture_half_float' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.HALF_FLOAT_OES;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === AlphaFormat ) { return 6406; }\r\n\t\t\tif ( p === RGBFormat ) { return 6407; }\r\n\t\t\tif ( p === RGBAFormat ) { return 6408; }\r\n\t\t\tif ( p === LuminanceFormat ) { return 6409; }\r\n\t\t\tif ( p === LuminanceAlphaFormat ) { return 6410; }\r\n\t\t\tif ( p === DepthFormat ) { return 6402; }\r\n\t\t\tif ( p === DepthStencilFormat ) { return 34041; }\r\n\t\t\tif ( p === RedFormat ) { return 6403; }\r\n\r\n\t\t\tif ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||\r\n\t\t\t\tp === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_s3tc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\tif ( p === RGB_S3TC_DXT1_Format ) { return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT1_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT3_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT5_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; }\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||\r\n\t\t\t\tp === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format ) { return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGB_PVRTC_2BPPV1_Format ) { return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGBA_PVRTC_4BPPV1_Format ) { return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGBA_PVRTC_2BPPV1_Format ) { return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; }\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGB_ETC1_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc1' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.COMPRESSED_RGB_ETC1_WEBGL;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||\r\n\t\t\t\tp === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_astc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\t// TODO Complete?\r\n\r\n\t\t\t\t\treturn p;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === UnsignedInt248Type ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) { return 34042; }\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_depth_texture' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.UNSIGNED_INT_24_8_WEBGL;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn { convert: convert };\r\n\r\n\t}\n\n\t/**\r\n\t * @author fernandojsg / http://fernandojsg.com\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction WebGLMultiviewRenderTarget( width, height, numViews, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t\tthis.depthBuffer = false;\r\n\t\tthis.stencilBuffer = false;\r\n\r\n\t\tthis.numViews = numViews;\r\n\r\n\t}\r\n\r\n\tWebGLMultiviewRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {\r\n\r\n\t\tconstructor: WebGLMultiviewRenderTarget,\r\n\r\n\t\tisWebGLMultiviewRenderTarget: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tWebGLRenderTarget.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.numViews = source.numViews;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetNumViews: function ( numViews ) {\r\n\r\n\t\t\tif ( this.numViews !== numViews ) {\r\n\r\n\t\t\t\tthis.numViews = numViews;\r\n\t\t\t\tthis.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author fernandojsg / http://fernandojsg.com\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction WebGLMultiview( renderer, gl ) {\r\n\r\n\t\tvar DEFAULT_NUMVIEWS = 2;\r\n\r\n\t\tvar extensions = renderer.extensions;\r\n\t\tvar properties = renderer.properties;\r\n\r\n\t\tvar renderTarget, currentRenderTarget;\r\n\t\tvar mat3, mat4, cameraArray, renderSize;\r\n\r\n\t\tvar available;\r\n\t\tvar maxNumViews = 0;\r\n\r\n\t\t//\r\n\r\n\t\tfunction isAvailable() {\r\n\r\n\t\t\tif ( available === undefined ) {\r\n\r\n\t\t\t\tvar extension = extensions.get( 'OVR_multiview2' );\r\n\r\n\t\t\t\tavailable = extension !== null && gl.getContextAttributes().antialias === false;\r\n\r\n\t\t\t\tif ( available ) {\r\n\r\n\t\t\t\t\tmaxNumViews = gl.getParameter( extension.MAX_VIEWS_OVR );\r\n\t\t\t\t\trenderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );\r\n\r\n\t\t\t\t\trenderSize = new Vector2();\r\n\t\t\t\t\tmat4 = [];\r\n\t\t\t\t\tmat3 = [];\r\n\t\t\t\t\tcameraArray = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < maxNumViews; i ++ ) {\r\n\r\n\t\t\t\t\t\tmat4[ i ] = new Matrix4();\r\n\t\t\t\t\t\tmat3[ i ] = new Matrix3();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn available;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getCameraArray( camera ) {\r\n\r\n\t\t\tif ( camera.isArrayCamera ) { return camera.cameras; }\r\n\r\n\t\t\tcameraArray[ 0 ] = camera;\r\n\r\n\t\t\treturn cameraArray;\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateCameraProjectionMatricesUniform( camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].copy( cameras[ i ].projectionMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'projectionMatrices', mat4 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateCameraViewMatricesUniform( camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].copy( cameras[ i ].matrixWorldInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'viewMatrices', mat4 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateObjectMatricesUniforms( object, camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );\r\n\t\t\t\tmat3[ i ].getNormalMatrix( mat4[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'modelViewMatrices', mat4 );\r\n\t\t\tuniforms.setValue( gl, 'normalMatrices', mat3 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction isMultiviewCompatible( camera ) {\r\n\r\n\t\t\tif ( camera.isArrayCamera === undefined ) { return true; }\r\n\r\n\t\t\tvar cameras = camera.cameras;\r\n\r\n\t\t\tif ( cameras.length > maxNumViews ) { return false; }\r\n\r\n\t\t\tfor ( var i = 1, il = cameras.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tif ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||\r\n\t\t\t\t\tcameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t}\r\n\r\n\t\tfunction resizeRenderTarget( camera ) {\r\n\r\n\t\t\tif ( currentRenderTarget ) {\r\n\r\n\t\t\t\trenderSize.set( currentRenderTarget.width, currentRenderTarget.height );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderer.getDrawingBufferSize( renderSize );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\tvar viewport = camera.cameras[ 0 ].viewport;\r\n\r\n\t\t\t\trenderTarget.setSize( viewport.z, viewport.w );\r\n\t\t\t\trenderTarget.setNumViews( camera.cameras.length );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderTarget.setSize( renderSize.x, renderSize.y );\r\n\t\t\t\trenderTarget.setNumViews( DEFAULT_NUMVIEWS );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction attachCamera( camera ) {\r\n\r\n\t\t\tif ( isMultiviewCompatible( camera ) === false ) { return; }\r\n\r\n\t\t\tcurrentRenderTarget = renderer.getRenderTarget();\r\n\t\t\tresizeRenderTarget( camera );\r\n\t\t\trenderer.setRenderTarget( renderTarget );\r\n\r\n\t\t}\r\n\r\n\t\tfunction detachCamera( camera ) {\r\n\r\n\t\t\tif ( renderTarget !== renderer.getRenderTarget() ) { return; }\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t\tflush( camera );\r\n\r\n\t\t}\r\n\r\n\t\tfunction flush( camera ) {\r\n\r\n\t\t\tvar srcRenderTarget = renderTarget;\r\n\t\t\tvar numViews = srcRenderTarget.numViews;\r\n\r\n\t\t\tvar srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;\r\n\r\n\t\t\tvar viewWidth = srcRenderTarget.width;\r\n\t\t\tvar viewHeight = srcRenderTarget.height;\r\n\r\n\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < numViews; i ++ ) {\r\n\r\n\t\t\t\t\tvar viewport = camera.cameras[ i ].viewport;\r\n\r\n\t\t\t\t\tvar x1 = viewport.x;\r\n\t\t\t\t\tvar y1 = viewport.y;\r\n\t\t\t\t\tvar x2 = x1 + viewport.z;\r\n\t\t\t\t\tvar y2 = y1 + viewport.w;\r\n\r\n\t\t\t\t\tgl.bindFramebuffer( 36008, srcFramebuffers[ i ] );\r\n\t\t\t\t\tgl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, 16384, 9728 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tgl.bindFramebuffer( 36008, srcFramebuffers[ 0 ] );\r\n\t\t\t\tgl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, 16384, 9728 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.isAvailable = isAvailable;\r\n\t\tthis.attachCamera = attachCamera;\r\n\t\tthis.detachCamera = detachCamera;\r\n\t\tthis.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;\r\n\t\tthis.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;\r\n\t\tthis.updateObjectMatricesUniforms = updateObjectMatricesUniforms;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Group() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Group';\r\n\r\n\t}\r\n\r\n\tGroup.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Group,\r\n\r\n\t\tisGroup: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ArrayCamera( array ) {\r\n\r\n\t\tPerspectiveCamera.call( this );\r\n\r\n\t\tthis.cameras = array || [];\r\n\r\n\t}\r\n\r\n\tArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {\r\n\r\n\t\tconstructor: ArrayCamera,\r\n\r\n\t\tisArrayCamera: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author jsantell / https://www.jsantell.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar cameraLPos = new Vector3();\r\n\tvar cameraRPos = new Vector3();\r\n\r\n\t/**\r\n\t * Assumes 2 cameras that are parallel and share an X-axis, and that\r\n\t * the cameras' projection and world matrices have already been set.\r\n\t * And that near and far planes are identical for both cameras.\r\n\t * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765\r\n\t */\r\n\tfunction setProjectionFromUnion( camera, cameraL, cameraR ) {\r\n\r\n\t\tcameraLPos.setFromMatrixPosition( cameraL.matrixWorld );\r\n\t\tcameraRPos.setFromMatrixPosition( cameraR.matrixWorld );\r\n\r\n\t\tvar ipd = cameraLPos.distanceTo( cameraRPos );\r\n\r\n\t\tvar projL = cameraL.projectionMatrix.elements;\r\n\t\tvar projR = cameraR.projectionMatrix.elements;\r\n\r\n\t\t// VR systems will have identical far and near planes, and\r\n\t\t// most likely identical top and bottom frustum extents.\r\n\t\t// Use the left camera for these values.\r\n\t\tvar near = projL[ 14 ] / ( projL[ 10 ] - 1 );\r\n\t\tvar far = projL[ 14 ] / ( projL[ 10 ] + 1 );\r\n\t\tvar topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];\r\n\t\tvar bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];\r\n\r\n\t\tvar leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];\r\n\t\tvar rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];\r\n\t\tvar left = near * leftFov;\r\n\t\tvar right = near * rightFov;\r\n\r\n\t\t// Calculate the new camera's position offset from the\r\n\t\t// left camera. xOffset should be roughly half `ipd`.\r\n\t\tvar zOffset = ipd / ( - leftFov + rightFov );\r\n\t\tvar xOffset = zOffset * - leftFov;\r\n\r\n\t\t// TODO: Better way to apply this offset?\r\n\t\tcameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );\r\n\t\tcamera.translateX( xOffset );\r\n\t\tcamera.translateZ( zOffset );\r\n\t\tcamera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );\r\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\r\n\r\n\t\t// Find the union of the frustum values of the cameras and scale\r\n\t\t// the values so that the near plane's position does not change in world space,\r\n\t\t// although must now be relative to the new union camera.\r\n\t\tvar near2 = near + zOffset;\r\n\t\tvar far2 = far + zOffset;\r\n\t\tvar left2 = left - xOffset;\r\n\t\tvar right2 = right + ( ipd - xOffset );\r\n\t\tvar top2 = topFov * far / far2 * near2;\r\n\t\tvar bottom2 = bottomFov * far / far2 * near2;\r\n\r\n\t\tcamera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebVRManager( renderer ) {\r\n\r\n\t\tvar renderWidth, renderHeight;\r\n\t\tvar scope = this;\r\n\r\n\t\tvar device = null;\r\n\t\tvar frameData = null;\r\n\r\n\t\tvar poseTarget = null;\r\n\r\n\t\tvar controllers = [];\r\n\t\tvar standingMatrix = new Matrix4();\r\n\t\tvar standingMatrixInverse = new Matrix4();\r\n\r\n\t\tvar framebufferScaleFactor = 1.0;\r\n\r\n\t\tvar referenceSpaceType = 'local-floor';\r\n\r\n\t\tif ( typeof window !== 'undefined' && 'VRFrameData' in window ) {\r\n\r\n\t\t\tframeData = new window.VRFrameData();\r\n\t\t\twindow.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );\r\n\r\n\t\t}\r\n\r\n\t\tvar matrixWorldInverse = new Matrix4();\r\n\t\tvar tempQuaternion = new Quaternion();\r\n\t\tvar tempPosition = new Vector3();\r\n\r\n\t\tvar cameraL = new PerspectiveCamera();\r\n\t\tcameraL.viewport = new Vector4();\r\n\t\tcameraL.layers.enable( 1 );\r\n\r\n\t\tvar cameraR = new PerspectiveCamera();\r\n\t\tcameraR.viewport = new Vector4();\r\n\t\tcameraR.layers.enable( 2 );\r\n\r\n\t\tvar cameraVR = new ArrayCamera( [ cameraL, cameraR ] );\r\n\t\tcameraVR.layers.enable( 1 );\r\n\t\tcameraVR.layers.enable( 2 );\r\n\r\n\t\t//\r\n\r\n\t\tfunction isPresenting() {\r\n\r\n\t\t\treturn device !== null && device.isPresenting === true;\r\n\r\n\t\t}\r\n\r\n\t\tvar currentSize = new Vector2(), currentPixelRatio;\r\n\r\n\t\tfunction onVRDisplayPresentChange() {\r\n\r\n\t\t\tif ( isPresenting() ) {\r\n\r\n\t\t\t\tvar eyeParameters = device.getEyeParameters( 'left' );\r\n\t\t\t\trenderWidth = 2 * eyeParameters.renderWidth * framebufferScaleFactor;\r\n\t\t\t\trenderHeight = eyeParameters.renderHeight * framebufferScaleFactor;\r\n\r\n\t\t\t\tcurrentPixelRatio = renderer.getPixelRatio();\r\n\t\t\t\trenderer.getSize( currentSize );\r\n\r\n\t\t\t\trenderer.setDrawingBufferSize( renderWidth, renderHeight, 1 );\r\n\r\n\t\t\t\tcameraL.viewport.set( 0, 0, renderWidth / 2, renderHeight );\r\n\t\t\t\tcameraR.viewport.set( renderWidth / 2, 0, renderWidth / 2, renderHeight );\r\n\r\n\t\t\t\tanimation.start();\r\n\r\n\t\t\t\tscope.dispatchEvent( { type: 'sessionstart' } );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( scope.enabled ) {\r\n\r\n\t\t\t\t\trenderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tanimation.stop();\r\n\r\n\t\t\t\tscope.dispatchEvent( { type: 'sessionend' } );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar triggers = [];\r\n\t\tvar grips = [];\r\n\r\n\t\tfunction findGamepad( id ) {\r\n\r\n\t\t\tvar gamepads = navigator.getGamepads && navigator.getGamepads();\r\n\r\n\t\t\tfor ( var i = 0, l = gamepads.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar gamepad = gamepads[ i ];\r\n\r\n\t\t\t\tif ( gamepad && ( gamepad.id === 'Daydream Controller' ||\r\n\t\t\t\t\tgamepad.id === 'Gear VR Controller' || gamepad.id === 'Oculus Go Controller' ||\r\n\t\t\t\t\tgamepad.id === 'OpenVR Gamepad' || gamepad.id.startsWith( 'Oculus Touch' ) ||\r\n\t\t\t\t\tgamepad.id.startsWith( 'HTC Vive Focus' ) ||\r\n\t\t\t\t\tgamepad.id.startsWith( 'Spatial Controller' ) ) ) {\r\n\r\n\t\t\t\t\tvar hand = gamepad.hand;\r\n\r\n\t\t\t\t\tif ( id === 0 && ( hand === '' || hand === 'right' ) ) { return gamepad; }\r\n\t\t\t\t\tif ( id === 1 && ( hand === 'left' ) ) { return gamepad; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateControllers() {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tvar controller = controllers[ i ];\r\n\r\n\t\t\t\tvar gamepad = findGamepad( i );\r\n\r\n\t\t\t\tif ( gamepad !== undefined && gamepad.pose !== undefined ) {\r\n\r\n\t\t\t\t\tif ( gamepad.pose === null ) { return; }\r\n\r\n\t\t\t\t\t// Pose\r\n\r\n\t\t\t\t\tvar pose = gamepad.pose;\r\n\r\n\t\t\t\t\tif ( pose.hasPosition === false ) { controller.position.set( 0.2, - 0.6, - 0.05 ); }\r\n\r\n\t\t\t\t\tif ( pose.position !== null ) { controller.position.fromArray( pose.position ); }\r\n\t\t\t\t\tif ( pose.orientation !== null ) { controller.quaternion.fromArray( pose.orientation ); }\r\n\t\t\t\t\tcontroller.matrix.compose( controller.position, controller.quaternion, controller.scale );\r\n\t\t\t\t\tcontroller.matrix.premultiply( standingMatrix );\r\n\t\t\t\t\tcontroller.matrix.decompose( controller.position, controller.quaternion, controller.scale );\r\n\t\t\t\t\tcontroller.matrixWorldNeedsUpdate = true;\r\n\t\t\t\t\tcontroller.visible = true;\r\n\r\n\t\t\t\t\t// Trigger\r\n\r\n\t\t\t\t\tvar buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;\r\n\r\n\t\t\t\t\tif ( triggers[ i ] === undefined ) { triggers[ i ] = false; }\r\n\r\n\t\t\t\t\tif ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {\r\n\r\n\t\t\t\t\t\ttriggers[ i ] = gamepad.buttons[ buttonId ].pressed;\r\n\r\n\t\t\t\t\t\tif ( triggers[ i ] === true ) {\r\n\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'selectstart' } );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'selectend' } );\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'select' } );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Grip\r\n\t\t\t\t\tbuttonId = 2;\r\n\r\n\t\t\t\t\tif ( grips[ i ] === undefined ) { grips[ i ] = false; }\r\n\r\n\t\t\t\t\t// Skip if the grip button doesn't exist on this controller\r\n\t\t\t\t\tif ( gamepad.buttons[ buttonId ] !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( grips[ i ] !== gamepad.buttons[ buttonId ].pressed ) {\r\n\r\n\t\t\t\t\t\t\tgrips[ i ] = gamepad.buttons[ buttonId ].pressed;\r\n\r\n\t\t\t\t\t\t\tif ( grips[ i ] === true ) {\r\n\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeezestart' } );\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeezeend' } );\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeeze' } );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateViewportFromBounds( viewport, bounds ) {\r\n\r\n\t\t\tif ( bounds !== null && bounds.length === 4 ) {\r\n\r\n\t\t\t\tviewport.set( bounds[ 0 ] * renderWidth, bounds[ 1 ] * renderHeight, bounds[ 2 ] * renderWidth, bounds[ 3 ] * renderHeight );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.getController = function ( id ) {\r\n\r\n\t\t\tvar controller = controllers[ id ];\r\n\r\n\t\t\tif ( controller === undefined ) {\r\n\r\n\t\t\t\tcontroller = new Group();\r\n\t\t\t\tcontroller.matrixAutoUpdate = false;\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\tcontrollers[ id ] = controller;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn controller;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDevice = function () {\r\n\r\n\t\t\treturn device;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDevice = function ( value ) {\r\n\r\n\t\t\tif ( value !== undefined ) { device = value; }\r\n\r\n\t\t\tanimation.setContext( value );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setFramebufferScaleFactor = function ( value ) {\r\n\r\n\t\t\tframebufferScaleFactor = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setReferenceSpaceType = function ( value ) {\r\n\r\n\t\t\treferenceSpaceType = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setPoseTarget = function ( object ) {\r\n\r\n\t\t\tif ( object !== undefined ) { poseTarget = object; }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCamera = function ( camera ) {\r\n\r\n\t\t\tvar userHeight = referenceSpaceType === 'local-floor' ? 1.6 : 0;\r\n\r\n\t\t\tdevice.depthNear = camera.near;\r\n\t\t\tdevice.depthFar = camera.far;\r\n\r\n\t\t\tdevice.getFrameData( frameData );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( referenceSpaceType === 'local-floor' ) {\r\n\r\n\t\t\t\tvar stageParameters = device.stageParameters;\r\n\r\n\t\t\t\tif ( stageParameters ) {\r\n\r\n\t\t\t\t\tstandingMatrix.fromArray( stageParameters.sittingToStandingTransform );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstandingMatrix.makeTranslation( 0, userHeight, 0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar pose = frameData.pose;\r\n\t\t\tvar poseObject = poseTarget !== null ? poseTarget : camera;\r\n\r\n\t\t\t// We want to manipulate poseObject by its position and quaternion components since users may rely on them.\r\n\t\t\tposeObject.matrix.copy( standingMatrix );\r\n\t\t\tposeObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );\r\n\r\n\t\t\tif ( pose.orientation !== null ) {\r\n\r\n\t\t\t\ttempQuaternion.fromArray( pose.orientation );\r\n\t\t\t\tposeObject.quaternion.multiply( tempQuaternion );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( pose.position !== null ) {\r\n\r\n\t\t\t\ttempQuaternion.setFromRotationMatrix( standingMatrix );\r\n\t\t\t\ttempPosition.fromArray( pose.position );\r\n\t\t\t\ttempPosition.applyQuaternion( tempQuaternion );\r\n\t\t\t\tposeObject.position.add( tempPosition );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tposeObject.updateMatrixWorld();\r\n\r\n\t\t\tvar children = poseObject.children;\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( true );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tcameraL.near = camera.near;\r\n\t\t\tcameraR.near = camera.near;\r\n\r\n\t\t\tcameraL.far = camera.far;\r\n\t\t\tcameraR.far = camera.far;\r\n\r\n\t\t\tcameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );\r\n\t\t\tcameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );\r\n\r\n\t\t\t// TODO (mrdoob) Double check this code\r\n\r\n\t\t\tstandingMatrixInverse.getInverse( standingMatrix );\r\n\r\n\t\t\tif ( referenceSpaceType === 'local-floor' ) {\r\n\r\n\t\t\t\tcameraL.matrixWorldInverse.multiply( standingMatrixInverse );\r\n\t\t\t\tcameraR.matrixWorldInverse.multiply( standingMatrixInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parent = poseObject.parent;\r\n\r\n\t\t\tif ( parent !== null ) {\r\n\r\n\t\t\t\tmatrixWorldInverse.getInverse( parent.matrixWorld );\r\n\r\n\t\t\t\tcameraL.matrixWorldInverse.multiply( matrixWorldInverse );\r\n\t\t\t\tcameraR.matrixWorldInverse.multiply( matrixWorldInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// envMap and Mirror needs camera.matrixWorld\r\n\r\n\t\t\tcameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );\r\n\t\t\tcameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );\r\n\r\n\t\t\tcameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );\r\n\t\t\tcameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );\r\n\r\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar layers = device.getLayers();\r\n\r\n\t\t\tif ( layers.length ) {\r\n\r\n\t\t\t\tvar layer = layers[ 0 ];\r\n\r\n\t\t\t\tupdateViewportFromBounds( cameraL.viewport, layer.leftBounds );\r\n\t\t\t\tupdateViewportFromBounds( cameraR.viewport, layer.rightBounds );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tupdateControllers();\r\n\r\n\t\t\treturn cameraVR;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getStandingMatrix = function () {\r\n\r\n\t\t\treturn standingMatrix;\r\n\r\n\t\t};\r\n\r\n\t\tthis.isPresenting = isPresenting;\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tanimation.setAnimationLoop( callback );\r\n\r\n\t\t\tif ( isPresenting() ) { animation.start(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.submitFrame = function () {\r\n\r\n\t\t\tif ( isPresenting() ) { device.submitFrame(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.dispose = function () {\r\n\r\n\t\t\tif ( typeof window !== 'undefined' ) {\r\n\r\n\t\t\t\twindow.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\t// DEPRECATED\r\n\r\n\t\tthis.setFrameOfReferenceType = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebVRManager: setFrameOfReferenceType() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( WebVRManager.prototype, EventDispatcher.prototype );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebXRManager( renderer, gl ) {\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar session = null;\r\n\r\n\t\t// var framebufferScaleFactor = 1.0;\r\n\r\n\t\tvar referenceSpace = null;\r\n\t\tvar referenceSpaceType = 'local-floor';\r\n\r\n\t\tvar pose = null;\r\n\t\tvar poseTarget = null;\r\n\r\n\t\tvar controllers = [];\r\n\t\tvar sortedInputSources = [];\r\n\r\n\t\tfunction isPresenting() {\r\n\r\n\t\t\treturn session !== null && referenceSpace !== null;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar cameraL = new PerspectiveCamera();\r\n\t\tcameraL.layers.enable( 1 );\r\n\t\tcameraL.viewport = new Vector4();\r\n\r\n\t\tvar cameraR = new PerspectiveCamera();\r\n\t\tcameraR.layers.enable( 2 );\r\n\t\tcameraR.viewport = new Vector4();\r\n\r\n\t\tvar cameraVR = new ArrayCamera( [ cameraL, cameraR ] );\r\n\t\tcameraVR.layers.enable( 1 );\r\n\t\tcameraVR.layers.enable( 2 );\r\n\r\n\t\t//\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.getController = function ( id ) {\r\n\r\n\t\t\tvar controller = controllers[ id ];\r\n\r\n\t\t\tif ( controller === undefined ) {\r\n\r\n\t\t\t\tcontroller = new Group();\r\n\t\t\t\tcontroller.matrixAutoUpdate = false;\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\tcontrollers[ id ] = controller;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn controller;\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tfunction onSessionEvent( event ) {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tif ( sortedInputSources[ i ] === event.inputSource ) {\r\n\r\n\t\t\t\t\tcontrollers[ i ].dispatchEvent( { type: event.type } );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction onSessionEnd() {\r\n\r\n\t\t\trenderer.setFramebuffer( null );\r\n\t\t\trenderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830\r\n\t\t\tanimation.stop();\r\n\r\n\t\t\tscope.dispatchEvent( { type: 'sessionend' } );\r\n\r\n\t\t}\r\n\r\n\t\tfunction onRequestReferenceSpace( value ) {\r\n\r\n\t\t\treferenceSpace = value;\r\n\r\n\t\t\tanimation.setContext( session );\r\n\t\t\tanimation.start();\r\n\r\n\t\t\tscope.dispatchEvent( { type: 'sessionstart' } );\r\n\r\n\t\t}\r\n\r\n\t\tthis.setFramebufferScaleFactor = function ( /* value */ ) {\r\n\r\n\t\t\t// framebufferScaleFactor = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setReferenceSpaceType = function ( value ) {\r\n\r\n\t\t\treferenceSpaceType = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getSession = function () {\r\n\r\n\t\t\treturn session;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setSession = function ( value ) {\r\n\r\n\t\t\tsession = value;\r\n\r\n\t\t\tif ( session !== null ) {\r\n\r\n\t\t\t\tsession.addEventListener( 'select', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'selectstart', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'selectend', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeeze', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeezestart', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeezeend', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'end', onSessionEnd );\r\n\r\n\t\t\t\t// eslint-disable-next-line no-undef\r\n\t\t\t\tsession.updateRenderState( { baseLayer: new XRWebGLLayer( session, gl,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tantialias: gl.getContextAttributes().antialias,\r\n\t\t\t\t\t\talpha: gl.getContextAttributes().alpha,\r\n\t\t\t\t\t\tdepth: gl.getContextAttributes().depth,\r\n\t\t\t\t\t\tstencil: gl.getContextAttributes().stencil\r\n\t\t\t\t\t}\r\n\t\t\t\t) } );\r\n\r\n\t\t\t\tsession.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );\r\n\r\n\t\t\t\t//\r\n\r\n\t\t\t\tsession.addEventListener( 'inputsourceschange', updateInputSources );\r\n\r\n\t\t\t\tupdateInputSources();\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tfunction updateInputSources() {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tsortedInputSources[ i ] = findInputSource( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction findInputSource( id ) {\r\n\r\n\t\t\tvar inputSources = session.inputSources;\r\n\r\n\t\t\tfor ( var i = 0; i < inputSources.length; i ++ ) {\r\n\r\n\t\t\t\tvar inputSource = inputSources[ i ];\r\n\t\t\t\tvar handedness = inputSource.handedness;\r\n\r\n\t\t\t\tif ( id === 0 && ( handedness === 'none' || handedness === 'right' ) ) { return inputSource; }\r\n\t\t\t\tif ( id === 1 && ( handedness === 'left' ) ) { return inputSource; }\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction updateCamera( camera, parent ) {\r\n\r\n\t\t\tif ( parent === null ) {\r\n\r\n\t\t\t\tcamera.matrixWorld.copy( camera.matrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tcamera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\r\n\r\n\t\t}\r\n\r\n\t\tthis.setPoseTarget = function ( object ) {\r\n\r\n\t\t\tif ( object !== undefined ) { poseTarget = object; }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCamera = function ( camera ) {\r\n\r\n\t\t\tvar parent = camera.parent;\r\n\t\t\tvar cameras = cameraVR.cameras;\r\n\t\t\tvar object = poseTarget || camera;\r\n\r\n\t\t\tupdateCamera( cameraVR, parent );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tupdateCamera( cameras[ i ], parent );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update camera and its children\r\n\t\t\tobject.matrixWorld.copy( cameraVR.matrixWorld );\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( true );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\r\n\r\n\t\t\treturn cameraVR;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCameraPose = function ( ) {\r\n\r\n\t\t\treturn pose;\r\n\r\n\t\t};\r\n\r\n\t\tthis.isPresenting = isPresenting;\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar onAnimationFrameCallback = null;\r\n\r\n\t\tfunction onAnimationFrame( time, frame ) {\r\n\r\n\t\t\tpose = frame.getViewerPose( referenceSpace );\r\n\r\n\t\t\tif ( pose !== null ) {\r\n\r\n\t\t\t\tvar views = pose.views;\r\n\t\t\t\tvar baseLayer = session.renderState.baseLayer;\r\n\r\n\t\t\t\trenderer.setFramebuffer( baseLayer.framebuffer );\r\n\r\n\t\t\t\tfor ( var i = 0; i < views.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar view = views[ i ];\r\n\t\t\t\t\tvar viewport = baseLayer.getViewport( view );\r\n\t\t\t\t\tvar viewMatrix = view.transform.inverse.matrix;\r\n\r\n\t\t\t\t\tvar camera = cameraVR.cameras[ i ];\r\n\t\t\t\t\tcamera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );\r\n\t\t\t\t\tcamera.projectionMatrix.fromArray( view.projectionMatrix );\r\n\t\t\t\t\tcamera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );\r\n\r\n\t\t\t\t\tif ( i === 0 ) {\r\n\r\n\t\t\t\t\t\tcameraVR.matrix.copy( camera.matrix );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tvar controller = controllers[ i ];\r\n\r\n\t\t\t\tvar inputSource = sortedInputSources[ i ];\r\n\r\n\t\t\t\tif ( inputSource ) {\r\n\r\n\t\t\t\t\tvar inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );\r\n\r\n\t\t\t\t\tif ( inputPose !== null ) {\r\n\r\n\t\t\t\t\t\tcontroller.matrix.fromArray( inputPose.transform.matrix );\r\n\t\t\t\t\t\tcontroller.matrix.decompose( controller.position, controller.rotation, controller.scale );\r\n\t\t\t\t\t\tcontroller.visible = true;\r\n\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( onAnimationFrameCallback ) { onAnimationFrameCallback( time, frame ); }\r\n\r\n\t\t}\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\t\tanimation.setAnimationLoop( onAnimationFrame );\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tonAnimationFrameCallback = callback;\r\n\r\n\t\t};\r\n\r\n\t\tthis.dispose = function () {};\r\n\r\n\t\t// DEPRECATED\r\n\r\n\t\tthis.getStandingMatrix = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );\r\n\t\t\treturn new Matrix4();\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDevice = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: getDevice() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDevice = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: setDevice() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setFrameOfReferenceType = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: setFrameOfReferenceType() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.submitFrame = function () {};\r\n\r\n\t}\r\n\r\n\tObject.assign( WebXRManager.prototype, EventDispatcher.prototype );\n\n\t/**\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction WebGLRenderer( parameters ) {\r\n\r\n\t\tparameters = parameters || {};\r\n\r\n\t\tvar _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),\r\n\t\t\t_context = parameters.context !== undefined ? parameters.context : null,\r\n\r\n\t\t\t_alpha = parameters.alpha !== undefined ? parameters.alpha : false,\r\n\t\t\t_depth = parameters.depth !== undefined ? parameters.depth : true,\r\n\t\t\t_stencil = parameters.stencil !== undefined ? parameters.stencil : true,\r\n\t\t\t_antialias = parameters.antialias !== undefined ? parameters.antialias : false,\r\n\t\t\t_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,\r\n\t\t\t_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,\r\n\t\t\t_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',\r\n\t\t\t_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;\r\n\r\n\t\tvar currentRenderList = null;\r\n\t\tvar currentRenderState = null;\r\n\r\n\t\t// public properties\r\n\r\n\t\tthis.domElement = _canvas;\r\n\r\n\t\t// Debug configuration container\r\n\t\tthis.debug = {\r\n\r\n\t\t\t/**\r\n\t\t\t * Enables error checking and reporting when shader programs are being compiled\r\n\t\t\t * @type {boolean}\r\n\t\t\t */\r\n\t\t\tcheckShaderErrors: true\r\n\t\t};\r\n\r\n\t\t// clearing\r\n\r\n\t\tthis.autoClear = true;\r\n\t\tthis.autoClearColor = true;\r\n\t\tthis.autoClearDepth = true;\r\n\t\tthis.autoClearStencil = true;\r\n\r\n\t\t// scene graph\r\n\r\n\t\tthis.sortObjects = true;\r\n\r\n\t\t// user-defined clipping\r\n\r\n\t\tthis.clippingPlanes = [];\r\n\t\tthis.localClippingEnabled = false;\r\n\r\n\t\t// physically based shading\r\n\r\n\t\tthis.gammaFactor = 2.0;\t// for backwards compatibility\r\n\t\tthis.gammaOutput = false;\r\n\r\n\t\t// physical lights\r\n\r\n\t\tthis.physicallyCorrectLights = false;\r\n\r\n\t\t// tone mapping\r\n\r\n\t\tthis.toneMapping = LinearToneMapping;\r\n\t\tthis.toneMappingExposure = 1.0;\r\n\t\tthis.toneMappingWhitePoint = 1.0;\r\n\r\n\t\t// morphs\r\n\r\n\t\tthis.maxMorphTargets = 8;\r\n\t\tthis.maxMorphNormals = 4;\r\n\r\n\t\t// internal properties\r\n\r\n\t\tvar _this = this,\r\n\r\n\t\t\t_isContextLost = false,\r\n\r\n\t\t\t// internal state cache\r\n\r\n\t\t\t_framebuffer = null,\r\n\r\n\t\t\t_currentActiveCubeFace = 0,\r\n\t\t\t_currentActiveMipmapLevel = 0,\r\n\t\t\t_currentRenderTarget = null,\r\n\t\t\t_currentFramebuffer = null,\r\n\t\t\t_currentMaterialId = - 1,\r\n\r\n\t\t\t// geometry and program caching\r\n\r\n\t\t\t_currentGeometryProgram = {\r\n\t\t\t\tgeometry: null,\r\n\t\t\t\tprogram: null,\r\n\t\t\t\twireframe: false\r\n\t\t\t},\r\n\r\n\t\t\t_currentCamera = null,\r\n\t\t\t_currentArrayCamera = null,\r\n\r\n\t\t\t_currentViewport = new Vector4(),\r\n\t\t\t_currentScissor = new Vector4(),\r\n\t\t\t_currentScissorTest = null,\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_width = _canvas.width,\r\n\t\t\t_height = _canvas.height,\r\n\r\n\t\t\t_pixelRatio = 1,\r\n\r\n\t\t\t_viewport = new Vector4( 0, 0, _width, _height ),\r\n\t\t\t_scissor = new Vector4( 0, 0, _width, _height ),\r\n\t\t\t_scissorTest = false,\r\n\r\n\t\t\t// frustum\r\n\r\n\t\t\t_frustum = new Frustum(),\r\n\r\n\t\t\t// clipping\r\n\r\n\t\t\t_clipping = new WebGLClipping(),\r\n\t\t\t_clippingEnabled = false,\r\n\t\t\t_localClippingEnabled = false,\r\n\r\n\t\t\t// camera matrices cache\r\n\r\n\t\t\t_projScreenMatrix = new Matrix4(),\r\n\r\n\t\t\t_vector3 = new Vector3();\r\n\r\n\t\tfunction getTargetPixelRatio() {\r\n\r\n\t\t\treturn _currentRenderTarget === null ? _pixelRatio : 1;\r\n\r\n\t\t}\r\n\r\n\t\t// initialize\r\n\r\n\t\tvar _gl;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tvar contextAttributes = {\r\n\t\t\t\talpha: _alpha,\r\n\t\t\t\tdepth: _depth,\r\n\t\t\t\tstencil: _stencil,\r\n\t\t\t\tantialias: _antialias,\r\n\t\t\t\tpremultipliedAlpha: _premultipliedAlpha,\r\n\t\t\t\tpreserveDrawingBuffer: _preserveDrawingBuffer,\r\n\t\t\t\tpowerPreference: _powerPreference,\r\n\t\t\t\tfailIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat,\r\n\t\t\t\txrCompatible: true\r\n\t\t\t};\r\n\r\n\t\t\t// event listeners must be registered before WebGL context is created, see #12753\r\n\r\n\t\t\t_canvas.addEventListener( 'webglcontextlost', onContextLost, false );\r\n\t\t\t_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );\r\n\r\n\t\t\t_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );\r\n\r\n\t\t\tif ( _gl === null ) {\r\n\r\n\t\t\t\tif ( _canvas.getContext( 'webgl' ) !== null ) {\r\n\r\n\t\t\t\t\tthrow new Error( 'Error creating WebGL context with your selected attributes.' );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthrow new Error( 'Error creating WebGL context.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Some experimental-webgl implementations do not have getShaderPrecisionFormat\r\n\r\n\t\t\tif ( _gl.getShaderPrecisionFormat === undefined ) {\r\n\r\n\t\t\t\t_gl.getShaderPrecisionFormat = function () {\r\n\r\n\t\t\t\t\treturn { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t} catch ( error ) {\r\n\r\n\t\t\tconsole.error( 'THREE.WebGLRenderer: ' + error.message );\r\n\t\t\tthrow error;\r\n\r\n\t\t}\r\n\r\n\t\tvar extensions, capabilities, state, info;\r\n\t\tvar properties, textures, attributes, geometries, objects;\r\n\t\tvar programCache, renderLists, renderStates;\r\n\r\n\t\tvar background, morphtargets, bufferRenderer, indexedBufferRenderer;\r\n\r\n\t\tvar utils;\r\n\r\n\t\tfunction initGLContext() {\r\n\r\n\t\t\textensions = new WebGLExtensions( _gl );\r\n\r\n\t\t\tcapabilities = new WebGLCapabilities( _gl, extensions, parameters );\r\n\r\n\t\t\tif ( capabilities.isWebGL2 === false ) {\r\n\r\n\t\t\t\textensions.get( 'WEBGL_depth_texture' );\r\n\t\t\t\textensions.get( 'OES_texture_float' );\r\n\t\t\t\textensions.get( 'OES_texture_half_float' );\r\n\t\t\t\textensions.get( 'OES_texture_half_float_linear' );\r\n\t\t\t\textensions.get( 'OES_standard_derivatives' );\r\n\t\t\t\textensions.get( 'OES_element_index_uint' );\r\n\t\t\t\textensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\textensions.get( 'OES_texture_float_linear' );\r\n\r\n\t\t\tutils = new WebGLUtils( _gl, extensions, capabilities );\r\n\r\n\t\t\tstate = new WebGLState( _gl, extensions, capabilities );\r\n\t\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\r\n\t\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t\tinfo = new WebGLInfo( _gl );\r\n\t\t\tproperties = new WebGLProperties();\r\n\t\t\ttextures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );\r\n\t\t\tattributes = new WebGLAttributes( _gl );\r\n\t\t\tgeometries = new WebGLGeometries( _gl, attributes, info );\r\n\t\t\tobjects = new WebGLObjects( _gl, geometries, attributes, info );\r\n\t\t\tmorphtargets = new WebGLMorphtargets( _gl );\r\n\t\t\tprogramCache = new WebGLPrograms( _this, extensions, capabilities );\r\n\t\t\trenderLists = new WebGLRenderLists();\r\n\t\t\trenderStates = new WebGLRenderStates();\r\n\r\n\t\t\tbackground = new WebGLBackground( _this, state, objects, _premultipliedAlpha );\r\n\r\n\t\t\tbufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );\r\n\t\t\tindexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );\r\n\r\n\t\t\tinfo.programs = programCache.programs;\r\n\r\n\t\t\t_this.capabilities = capabilities;\r\n\t\t\t_this.extensions = extensions;\r\n\t\t\t_this.properties = properties;\r\n\t\t\t_this.renderLists = renderLists;\r\n\t\t\t_this.state = state;\r\n\t\t\t_this.info = info;\r\n\r\n\t\t}\r\n\r\n\t\tinitGLContext();\r\n\r\n\t\t// xr\r\n\r\n\t\tvar xr = ( typeof navigator !== 'undefined' && 'xr' in navigator ) ? new WebXRManager( _this, _gl ) : new WebVRManager( _this );\r\n\r\n\t\tthis.xr = xr;\r\n\r\n\t\t// Multiview\r\n\r\n\t\tvar multiview = new WebGLMultiview( _this, _gl );\r\n\r\n\t\t// shadow map\r\n\r\n\t\tvar shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );\r\n\r\n\t\tthis.shadowMap = shadowMap;\r\n\r\n\t\t// API\r\n\r\n\t\tthis.getContext = function () {\r\n\r\n\t\t\treturn _gl;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getContextAttributes = function () {\r\n\r\n\t\t\treturn _gl.getContextAttributes();\r\n\r\n\t\t};\r\n\r\n\t\tthis.forceContextLoss = function () {\r\n\r\n\t\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\r\n\t\t\tif ( extension ) { extension.loseContext(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.forceContextRestore = function () {\r\n\r\n\t\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\r\n\t\t\tif ( extension ) { extension.restoreContext(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getPixelRatio = function () {\r\n\r\n\t\t\treturn _pixelRatio;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setPixelRatio = function ( value ) {\r\n\r\n\t\t\tif ( value === undefined ) { return; }\r\n\r\n\t\t\t_pixelRatio = value;\r\n\r\n\t\t\tthis.setSize( _width, _height, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getSize = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( _width, _height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setSize = function ( width, height, updateStyle ) {\r\n\r\n\t\t\tif ( xr.isPresenting() ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Can\\'t change size while VR device is presenting.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_width = width;\r\n\t\t\t_height = height;\r\n\r\n\t\t\t_canvas.width = Math.floor( width * _pixelRatio );\r\n\t\t\t_canvas.height = Math.floor( height * _pixelRatio );\r\n\r\n\t\t\tif ( updateStyle !== false ) {\r\n\r\n\t\t\t\t_canvas.style.width = width + 'px';\r\n\t\t\t\t_canvas.style.height = height + 'px';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setViewport( 0, 0, width, height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDrawingBufferSize = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDrawingBufferSize = function ( width, height, pixelRatio ) {\r\n\r\n\t\t\t_width = width;\r\n\t\t\t_height = height;\r\n\r\n\t\t\t_pixelRatio = pixelRatio;\r\n\r\n\t\t\t_canvas.width = Math.floor( width * pixelRatio );\r\n\t\t\t_canvas.height = Math.floor( height * pixelRatio );\r\n\r\n\t\t\tthis.setViewport( 0, 0, width, height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCurrentViewport = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector4();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( _currentViewport );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getViewport = function ( target ) {\r\n\r\n\t\t\treturn target.copy( _viewport );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setViewport = function ( x, y, width, height ) {\r\n\r\n\t\t\tif ( x.isVector4 ) {\r\n\r\n\t\t\t\t_viewport.set( x.x, x.y, x.z, x.w );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_viewport.set( x, y, width, height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getScissor = function ( target ) {\r\n\r\n\t\t\treturn target.copy( _scissor );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setScissor = function ( x, y, width, height ) {\r\n\r\n\t\t\tif ( x.isVector4 ) {\r\n\r\n\t\t\t\t_scissor.set( x.x, x.y, x.z, x.w );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_scissor.set( x, y, width, height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getScissorTest = function () {\r\n\r\n\t\t\treturn _scissorTest;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setScissorTest = function ( boolean ) {\r\n\r\n\t\t\tstate.setScissorTest( _scissorTest = boolean );\r\n\r\n\t\t};\r\n\r\n\t\t// Clearing\r\n\r\n\t\tthis.getClearColor = function () {\r\n\r\n\t\t\treturn background.getClearColor();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setClearColor = function () {\r\n\r\n\t\t\tbackground.setClearColor.apply( background, arguments );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getClearAlpha = function () {\r\n\r\n\t\t\treturn background.getClearAlpha();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setClearAlpha = function () {\r\n\r\n\t\t\tbackground.setClearAlpha.apply( background, arguments );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clear = function ( color, depth, stencil ) {\r\n\r\n\t\t\tvar bits = 0;\r\n\r\n\t\t\tif ( color === undefined || color ) { bits |= 16384; }\r\n\t\t\tif ( depth === undefined || depth ) { bits |= 256; }\r\n\t\t\tif ( stencil === undefined || stencil ) { bits |= 1024; }\r\n\r\n\t\t\t_gl.clear( bits );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearColor = function () {\r\n\r\n\t\t\tthis.clear( true, false, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearDepth = function () {\r\n\r\n\t\t\tthis.clear( false, true, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearStencil = function () {\r\n\r\n\t\t\tthis.clear( false, false, true );\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tthis.dispose = function () {\r\n\r\n\t\t\t_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );\r\n\t\t\t_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );\r\n\r\n\t\t\trenderLists.dispose();\r\n\t\t\trenderStates.dispose();\r\n\t\t\tproperties.dispose();\r\n\t\t\tobjects.dispose();\r\n\r\n\t\t\txr.dispose();\r\n\r\n\t\t\tanimation.stop();\r\n\r\n\t\t};\r\n\r\n\t\t// Events\r\n\r\n\t\tfunction onContextLost( event ) {\r\n\r\n\t\t\tevent.preventDefault();\r\n\r\n\t\t\tconsole.log( 'THREE.WebGLRenderer: Context Lost.' );\r\n\r\n\t\t\t_isContextLost = true;\r\n\r\n\t\t}\r\n\r\n\t\tfunction onContextRestore( /* event */ ) {\r\n\r\n\t\t\tconsole.log( 'THREE.WebGLRenderer: Context Restored.' );\r\n\r\n\t\t\t_isContextLost = false;\r\n\r\n\t\t\tinitGLContext();\r\n\r\n\t\t}\r\n\r\n\t\tfunction onMaterialDispose( event ) {\r\n\r\n\t\t\tvar material = event.target;\r\n\r\n\t\t\tmaterial.removeEventListener( 'dispose', onMaterialDispose );\r\n\r\n\t\t\tdeallocateMaterial( material );\r\n\r\n\t\t}\r\n\r\n\t\t// Buffer deallocation\r\n\r\n\t\tfunction deallocateMaterial( material ) {\r\n\r\n\t\t\treleaseMaterialProgramReference( material );\r\n\r\n\t\t\tproperties.remove( material );\r\n\r\n\t\t}\r\n\r\n\r\n\t\tfunction releaseMaterialProgramReference( material ) {\r\n\r\n\t\t\tvar programInfo = properties.get( material ).program;\r\n\r\n\t\t\tmaterial.program = undefined;\r\n\r\n\t\t\tif ( programInfo !== undefined ) {\r\n\r\n\t\t\t\tprogramCache.releaseProgram( programInfo );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Buffer rendering\r\n\r\n\t\tfunction renderObjectImmediate( object, program ) {\r\n\r\n\t\t\tobject.render( function ( object ) {\r\n\r\n\t\t\t\t_this.renderBufferImmediate( object, program );\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\tthis.renderBufferImmediate = function ( object, program ) {\r\n\r\n\t\t\tstate.initAttributes();\r\n\r\n\t\t\tvar buffers = properties.get( object );\r\n\r\n\t\t\tif ( object.hasPositions && ! buffers.position ) { buffers.position = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasNormals && ! buffers.normal ) { buffers.normal = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasUvs && ! buffers.uv ) { buffers.uv = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasColors && ! buffers.color ) { buffers.color = _gl.createBuffer(); }\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tif ( object.hasPositions ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.position );\r\n\t\t\t\t_gl.bufferData( 34962, object.positionArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.position );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasNormals ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.normal );\r\n\t\t\t\t_gl.bufferData( 34962, object.normalArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.normal );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasUvs ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.uv );\r\n\t\t\t\t_gl.bufferData( 34962, object.uvArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.uv );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasColors ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.color );\r\n\t\t\t\t_gl.bufferData( 34962, object.colorArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.color );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.disableUnusedAttributes();\r\n\r\n\t\t\t_gl.drawArrays( 4, 0, object.count );\r\n\r\n\t\t\tobject.count = 0;\r\n\r\n\t\t};\r\n\r\n\t\tthis.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {\r\n\r\n\t\t\tvar frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );\r\n\r\n\t\t\tvar program = setProgram( camera, fog, material, object );\r\n\r\n\t\t\tstate.setMaterial( material, frontFaceCW );\r\n\r\n\t\t\tvar updateBuffers = false;\r\n\r\n\t\t\tif ( _currentGeometryProgram.geometry !== geometry.id ||\r\n\t\t\t\t_currentGeometryProgram.program !== program.id ||\r\n\t\t\t\t_currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {\r\n\r\n\t\t\t\t_currentGeometryProgram.geometry = geometry.id;\r\n\t\t\t\t_currentGeometryProgram.program = program.id;\r\n\t\t\t\t_currentGeometryProgram.wireframe = material.wireframe === true;\r\n\t\t\t\tupdateBuffers = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.morphTargets || material.morphNormals ) {\r\n\r\n\t\t\t\tmorphtargets.update( object, geometry, material, program );\r\n\r\n\t\t\t\tupdateBuffers = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar index = geometry.index;\r\n\t\t\tvar position = geometry.attributes.position;\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( index !== null && index.count === 0 ) { return; }\r\n\t\t\tif ( position === undefined || position.count === 0 ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar rangeFactor = 1;\r\n\r\n\t\t\tif ( material.wireframe === true ) {\r\n\r\n\t\t\t\tindex = geometries.getWireframeAttribute( geometry );\r\n\t\t\t\trangeFactor = 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute;\r\n\t\t\tvar renderer = bufferRenderer;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tattribute = attributes.get( index );\r\n\r\n\t\t\t\trenderer = indexedBufferRenderer;\r\n\t\t\t\trenderer.setIndex( attribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( updateBuffers ) {\r\n\r\n\t\t\t\tsetupVertexAttributes( object, geometry, material, program );\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\t_gl.bindBuffer( 34963, attribute.buffer );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar dataCount = ( index !== null ) ? index.count : position.count;\r\n\r\n\t\t\tvar rangeStart = geometry.drawRange.start * rangeFactor;\r\n\t\t\tvar rangeCount = geometry.drawRange.count * rangeFactor;\r\n\r\n\t\t\tvar groupStart = group !== null ? group.start * rangeFactor : 0;\r\n\t\t\tvar groupCount = group !== null ? group.count * rangeFactor : Infinity;\r\n\r\n\t\t\tvar drawStart = Math.max( rangeStart, groupStart );\r\n\t\t\tvar drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;\r\n\r\n\t\t\tvar drawCount = Math.max( 0, drawEnd - drawStart + 1 );\r\n\r\n\t\t\tif ( drawCount === 0 ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( object.isMesh ) {\r\n\r\n\t\t\t\tif ( material.wireframe === true ) {\r\n\r\n\t\t\t\t\tstate.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );\r\n\t\t\t\t\trenderer.setMode( 1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderer.setMode( 4 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isLine ) {\r\n\r\n\t\t\t\tvar lineWidth = material.linewidth;\r\n\r\n\t\t\t\tif ( lineWidth === undefined ) { lineWidth = 1; } // Not using Line*Material\r\n\r\n\t\t\t\tstate.setLineWidth( lineWidth * getTargetPixelRatio() );\r\n\r\n\t\t\t\tif ( object.isLineSegments ) {\r\n\r\n\t\t\t\t\trenderer.setMode( 1 );\r\n\r\n\t\t\t\t} else if ( object.isLineLoop ) {\r\n\r\n\t\t\t\t\trenderer.setMode( 2 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderer.setMode( 3 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isPoints ) {\r\n\r\n\t\t\t\trenderer.setMode( 0 );\r\n\r\n\t\t\t} else if ( object.isSprite ) {\r\n\r\n\t\t\t\trenderer.setMode( 4 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.isInstancedMesh ) {\r\n\r\n\t\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, object.count );\r\n\r\n\t\t\t} else if ( geometry.isInstancedBufferGeometry ) {\r\n\r\n\t\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, geometry.maxInstancedCount );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderer.render( drawStart, drawCount );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tfunction setupVertexAttributes( object, geometry, material, program ) {\r\n\r\n\t\t\tif ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {\r\n\r\n\t\t\t\tif ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { return; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.initAttributes();\r\n\r\n\t\t\tvar geometryAttributes = geometry.attributes;\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tvar materialDefaultAttributeValues = material.defaultAttributeValues;\r\n\r\n\t\t\tfor ( var name in programAttributes ) {\r\n\r\n\t\t\t\tvar programAttribute = programAttributes[ name ];\r\n\r\n\t\t\t\tif ( programAttribute >= 0 ) {\r\n\r\n\t\t\t\t\tvar geometryAttribute = geometryAttributes[ name ];\r\n\r\n\t\t\t\t\tif ( geometryAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tvar normalized = geometryAttribute.normalized;\r\n\t\t\t\t\t\tvar size = geometryAttribute.itemSize;\r\n\r\n\t\t\t\t\t\tvar attribute = attributes.get( geometryAttribute );\r\n\r\n\t\t\t\t\t\t// TODO Attribute may not be available on context restore\r\n\r\n\t\t\t\t\t\tif ( attribute === undefined ) { continue; }\r\n\r\n\t\t\t\t\t\tvar buffer = attribute.buffer;\r\n\t\t\t\t\t\tvar type = attribute.type;\r\n\t\t\t\t\t\tvar bytesPerElement = attribute.bytesPerElement;\r\n\r\n\t\t\t\t\t\tif ( geometryAttribute.isInterleavedBufferAttribute ) {\r\n\r\n\t\t\t\t\t\t\tvar data = geometryAttribute.data;\r\n\t\t\t\t\t\t\tvar stride = data.stride;\r\n\t\t\t\t\t\t\tvar offset = geometryAttribute.offset;\r\n\r\n\t\t\t\t\t\t\tif ( data && data.isInstancedInterleavedBuffer ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );\r\n\r\n\t\t\t\t\t\t\t\tif ( geometry.maxInstancedCount === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tgeometry.maxInstancedCount = data.meshPerAttribute * data.count;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\t\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tif ( geometryAttribute.isInstancedBufferAttribute ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );\r\n\r\n\t\t\t\t\t\t\t\tif ( geometry.maxInstancedCount === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tgeometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\t\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else if ( name === 'instanceMatrix' ) {\r\n\r\n\t\t\t\t\t\tvar attribute = attributes.get( object.instanceMatrix );\r\n\r\n\t\t\t\t\t\t// TODO Attribute may not be available on context restore\r\n\r\n\t\t\t\t\t\tif ( attribute === undefined ) { continue; }\r\n\r\n\t\t\t\t\t\tvar buffer = attribute.buffer;\r\n\t\t\t\t\t\tvar type = attribute.type;\r\n\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 0, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 1, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 2, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 3, 1 );\r\n\r\n\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );\r\n\r\n\t\t\t\t\t} else if ( materialDefaultAttributeValues !== undefined ) {\r\n\r\n\t\t\t\t\t\tvar value = materialDefaultAttributeValues[ name ];\r\n\r\n\t\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\t\tswitch ( value.length ) {\r\n\r\n\t\t\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib2fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib3fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase 4:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib4fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib1fv( programAttribute, value );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.disableUnusedAttributes();\r\n\r\n\t\t}\r\n\r\n\t\t// Compile\r\n\r\n\t\tthis.compile = function ( scene, camera ) {\r\n\r\n\t\t\tcurrentRenderState = renderStates.get( scene, camera );\r\n\t\t\tcurrentRenderState.init();\r\n\r\n\t\t\tscene.traverse( function ( object ) {\r\n\r\n\t\t\t\tif ( object.isLight ) {\r\n\r\n\t\t\t\t\tcurrentRenderState.pushLight( object );\r\n\r\n\t\t\t\t\tif ( object.castShadow ) {\r\n\r\n\t\t\t\t\t\tcurrentRenderState.pushShadow( object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tcurrentRenderState.setupLights( camera );\r\n\r\n\t\t\tscene.traverse( function ( object ) {\r\n\r\n\t\t\t\tif ( object.material ) {\r\n\r\n\t\t\t\t\tif ( Array.isArray( object.material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < object.material.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tinitMaterial( object.material[ i ], scene.fog, object );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tinitMaterial( object.material, scene.fog, object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} );\r\n\r\n\t\t};\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar onAnimationFrameCallback = null;\r\n\r\n\t\tfunction onAnimationFrame( time ) {\r\n\r\n\t\t\tif ( xr.isPresenting() ) { return; }\r\n\t\t\tif ( onAnimationFrameCallback ) { onAnimationFrameCallback( time ); }\r\n\r\n\t\t}\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\t\tanimation.setAnimationLoop( onAnimationFrame );\r\n\r\n\t\tif ( typeof window !== 'undefined' ) { animation.setContext( window ); }\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tonAnimationFrameCallback = callback;\r\n\t\t\txr.setAnimationLoop( callback );\r\n\r\n\t\t\tanimation.start();\r\n\r\n\t\t};\r\n\r\n\t\t// Rendering\r\n\r\n\t\tthis.render = function ( scene, camera ) {\r\n\r\n\t\t\tvar renderTarget, forceClear;\r\n\r\n\t\t\tif ( arguments[ 2 ] !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );\r\n\t\t\t\trenderTarget = arguments[ 2 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( arguments[ 3 ] !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );\r\n\t\t\t\tforceClear = arguments[ 3 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! ( camera && camera.isCamera ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _isContextLost ) { return; }\r\n\r\n\t\t\t// reset caching for this frame\r\n\r\n\t\t\t_currentGeometryProgram.geometry = null;\r\n\t\t\t_currentGeometryProgram.program = null;\r\n\t\t\t_currentGeometryProgram.wireframe = false;\r\n\t\t\t_currentMaterialId = - 1;\r\n\t\t\t_currentCamera = null;\r\n\r\n\t\t\t// update scene graph\r\n\r\n\t\t\tif ( scene.autoUpdate === true ) { scene.updateMatrixWorld(); }\r\n\r\n\t\t\t// update camera matrices and frustum\r\n\r\n\t\t\tif ( camera.parent === null ) { camera.updateMatrixWorld(); }\r\n\r\n\t\t\tif ( xr.enabled && xr.isPresenting() ) {\r\n\r\n\t\t\t\tcamera = xr.getCamera( camera );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tcurrentRenderState = renderStates.get( scene, camera );\r\n\t\t\tcurrentRenderState.init();\r\n\r\n\t\t\tscene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );\r\n\r\n\t\t\t_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\r\n\t\t\t_frustum.setFromMatrix( _projScreenMatrix );\r\n\r\n\t\t\t_localClippingEnabled = this.localClippingEnabled;\r\n\t\t\t_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );\r\n\r\n\t\t\tcurrentRenderList = renderLists.get( scene, camera );\r\n\t\t\tcurrentRenderList.init();\r\n\r\n\t\t\tprojectObject( scene, camera, 0, _this.sortObjects );\r\n\r\n\t\t\tif ( _this.sortObjects === true ) {\r\n\r\n\t\t\t\tcurrentRenderList.sort();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( _clippingEnabled ) { _clipping.beginShadows(); }\r\n\r\n\t\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\r\n\r\n\t\t\tshadowMap.render( shadowsArray, scene, camera );\r\n\r\n\t\t\tcurrentRenderState.setupLights( camera );\r\n\r\n\t\t\tif ( _clippingEnabled ) { _clipping.endShadows(); }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.info.autoReset ) { this.info.reset(); }\r\n\r\n\t\t\tif ( renderTarget !== undefined ) {\r\n\r\n\t\t\t\tthis.setRenderTarget( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( xr.enabled && multiview.isAvailable() ) {\r\n\r\n\t\t\t\tmultiview.attachCamera( camera );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tbackground.render( currentRenderList, scene, camera, forceClear );\r\n\r\n\t\t\t// render scene\r\n\r\n\t\t\tvar opaqueObjects = currentRenderList.opaque;\r\n\t\t\tvar transparentObjects = currentRenderList.transparent;\r\n\r\n\t\t\tif ( scene.overrideMaterial ) {\r\n\r\n\t\t\t\tvar overrideMaterial = scene.overrideMaterial;\r\n\r\n\t\t\t\tif ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera, overrideMaterial ); }\r\n\t\t\t\tif ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera, overrideMaterial ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// opaque pass (front-to-back order)\r\n\r\n\t\t\t\tif ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera ); }\r\n\r\n\t\t\t\t// transparent pass (back-to-front order)\r\n\r\n\t\t\t\tif ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tscene.onAfterRender( _this, scene, camera );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( _currentRenderTarget !== null ) {\r\n\r\n\t\t\t\t// Generate mipmap if we're using any kind of mipmap filtering\r\n\r\n\t\t\t\ttextures.updateRenderTargetMipmap( _currentRenderTarget );\r\n\r\n\t\t\t\t// resolve multisample renderbuffers to a single-sample texture if necessary\r\n\r\n\t\t\t\ttextures.updateMultisampleRenderTarget( _currentRenderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Ensure depth buffer writing is enabled so it can be cleared on next render\r\n\r\n\t\t\tstate.buffers.depth.setTest( true );\r\n\t\t\tstate.buffers.depth.setMask( true );\r\n\t\t\tstate.buffers.color.setMask( true );\r\n\r\n\t\t\tstate.setPolygonOffset( false );\r\n\r\n\t\t\tif ( xr.enabled ) {\r\n\r\n\t\t\t\tif ( multiview.isAvailable() ) {\r\n\r\n\t\t\t\t\tmultiview.detachCamera( camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\txr.submitFrame();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// _gl.finish();\r\n\r\n\t\t\tcurrentRenderList = null;\r\n\t\t\tcurrentRenderState = null;\r\n\r\n\t\t};\r\n\r\n\t\tfunction projectObject( object, camera, groupOrder, sortObjects ) {\r\n\r\n\t\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\t\tvar visible = object.layers.test( camera.layers );\r\n\r\n\t\t\tif ( visible ) {\r\n\r\n\t\t\t\tif ( object.isGroup ) {\r\n\r\n\t\t\t\t\tgroupOrder = object.renderOrder;\r\n\r\n\t\t\t\t} else if ( object.isLOD ) {\r\n\r\n\t\t\t\t\tif ( object.autoUpdate === true ) { object.update( camera ); }\r\n\r\n\t\t\t\t} else if ( object.isLight ) {\r\n\r\n\t\t\t\t\tcurrentRenderState.pushLight( object );\r\n\r\n\t\t\t\t\tif ( object.castShadow ) {\r\n\r\n\t\t\t\t\t\tcurrentRenderState.pushShadow( object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( object.isSprite ) {\r\n\r\n\t\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {\r\n\r\n\t\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar geometry = objects.update( object );\r\n\t\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\t\tif ( material.visible ) {\r\n\r\n\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( object.isImmediateRenderObject ) {\r\n\r\n\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcurrentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t} else if ( object.isMesh || object.isLine || object.isPoints ) {\r\n\r\n\t\t\t\t\tif ( object.isSkinnedMesh ) {\r\n\r\n\t\t\t\t\t\t// update skeleton only once in a frame\r\n\r\n\t\t\t\t\t\tif ( object.skeleton.frame !== info.render.frame ) {\r\n\r\n\t\t\t\t\t\t\tobject.skeleton.update();\r\n\t\t\t\t\t\t\tobject.skeleton.frame = info.render.frame;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {\r\n\r\n\t\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar geometry = objects.update( object );\r\n\t\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\r\n\r\n\t\t\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else if ( material.visible ) {\r\n\r\n\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tprojectObject( children[ i ], camera, groupOrder, sortObjects );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObjects( renderList, scene, camera, overrideMaterial ) {\r\n\r\n\t\t\tfor ( var i = 0, l = renderList.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar renderItem = renderList[ i ];\r\n\r\n\t\t\t\tvar object = renderItem.object;\r\n\t\t\t\tvar geometry = renderItem.geometry;\r\n\t\t\t\tvar material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;\r\n\t\t\t\tvar group = renderItem.group;\r\n\r\n\t\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\t\t_currentArrayCamera = camera;\r\n\r\n\t\t\t\t\tif ( xr.enabled && multiview.isAvailable() ) {\r\n\r\n\t\t\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tvar cameras = camera.cameras;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = cameras.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar camera2 = cameras[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( object.layers.test( camera2.layers ) ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.viewport( _currentViewport.copy( camera2.viewport ) );\r\n\r\n\t\t\t\t\t\t\t\tcurrentRenderState.setupLights( camera2 );\r\n\r\n\t\t\t\t\t\t\t\trenderObject( object, scene, camera2, geometry, material, group );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_currentArrayCamera = null;\r\n\r\n\t\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObject( object, scene, camera, geometry, material, group ) {\r\n\r\n\t\t\tobject.onBeforeRender( _this, scene, camera, geometry, material, group );\r\n\t\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\r\n\r\n\t\t\tobject.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );\r\n\t\t\tobject.normalMatrix.getNormalMatrix( object.modelViewMatrix );\r\n\r\n\t\t\tif ( object.isImmediateRenderObject ) {\r\n\r\n\t\t\t\tvar program = setProgram( camera, scene.fog, material, object );\r\n\r\n\t\t\t\tstate.setMaterial( material );\r\n\r\n\t\t\t\t_currentGeometryProgram.geometry = null;\r\n\t\t\t\t_currentGeometryProgram.program = null;\r\n\t\t\t\t_currentGeometryProgram.wireframe = false;\r\n\r\n\t\t\t\trenderObjectImmediate( object, program );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.onAfterRender( _this, scene, camera, geometry, material, group );\r\n\t\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\r\n\r\n\t\t}\r\n\r\n\t\tfunction initMaterial( material, fog, object ) {\r\n\r\n\t\t\tvar materialProperties = properties.get( material );\r\n\r\n\t\t\tvar lights = currentRenderState.state.lights;\r\n\t\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\r\n\r\n\t\t\tvar lightsStateVersion = lights.state.version;\r\n\r\n\t\t\tvar parameters = programCache.getParameters(\r\n\t\t\t\tmaterial, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );\r\n\r\n\t\t\tvar programCacheKey = programCache.getProgramCacheKey( material, parameters );\r\n\r\n\t\t\tvar program = materialProperties.program;\r\n\t\t\tvar programChange = true;\r\n\r\n\t\t\tif ( program === undefined ) {\r\n\r\n\t\t\t\t// new material\r\n\t\t\t\tmaterial.addEventListener( 'dispose', onMaterialDispose );\r\n\r\n\t\t\t} else if ( program.cacheKey !== programCacheKey ) {\r\n\r\n\t\t\t\t// changed glsl or parameters\r\n\t\t\t\treleaseMaterialProgramReference( material );\r\n\r\n\t\t\t} else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {\r\n\r\n\t\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\r\n\r\n\t\t\t\tprogramChange = false;\r\n\r\n\t\t\t} else if ( parameters.shaderID !== undefined ) {\r\n\r\n\t\t\t\t// same glsl and uniform list\r\n\t\t\t\treturn;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// only rebuild uniform list\r\n\t\t\t\tprogramChange = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( programChange ) {\r\n\r\n\t\t\t\tif ( parameters.shaderID ) {\r\n\r\n\t\t\t\t\tvar shader = ShaderLib[ parameters.shaderID ];\r\n\r\n\t\t\t\t\tmaterialProperties.shader = {\r\n\t\t\t\t\t\tname: material.type,\r\n\t\t\t\t\t\tuniforms: cloneUniforms( shader.uniforms ),\r\n\t\t\t\t\t\tvertexShader: shader.vertexShader,\r\n\t\t\t\t\t\tfragmentShader: shader.fragmentShader\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tmaterialProperties.shader = {\r\n\t\t\t\t\t\tname: material.type,\r\n\t\t\t\t\t\tuniforms: material.uniforms,\r\n\t\t\t\t\t\tvertexShader: material.vertexShader,\r\n\t\t\t\t\t\tfragmentShader: material.fragmentShader\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmaterial.onBeforeCompile( materialProperties.shader, _this );\r\n\r\n\t\t\t\t// Computing cache key again as onBeforeCompile may have changed the shaders\r\n\t\t\t\tprogramCacheKey = programCache.getProgramCacheKey( material, parameters );\r\n\r\n\t\t\t\tprogram = programCache.acquireProgram( material, materialProperties.shader, parameters, programCacheKey );\r\n\r\n\t\t\t\tmaterialProperties.program = program;\r\n\t\t\t\tmaterial.program = program;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tif ( material.morphTargets ) {\r\n\r\n\t\t\t\tmaterial.numSupportedMorphTargets = 0;\r\n\r\n\t\t\t\tfor ( var i = 0; i < _this.maxMorphTargets; i ++ ) {\r\n\r\n\t\t\t\t\tif ( programAttributes[ 'morphTarget' + i ] >= 0 ) {\r\n\r\n\t\t\t\t\t\tmaterial.numSupportedMorphTargets ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.morphNormals ) {\r\n\r\n\t\t\t\tmaterial.numSupportedMorphNormals = 0;\r\n\r\n\t\t\t\tfor ( var i = 0; i < _this.maxMorphNormals; i ++ ) {\r\n\r\n\t\t\t\t\tif ( programAttributes[ 'morphNormal' + i ] >= 0 ) {\r\n\r\n\t\t\t\t\t\tmaterial.numSupportedMorphNormals ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar uniforms = materialProperties.shader.uniforms;\r\n\r\n\t\t\tif ( ! material.isShaderMaterial &&\r\n\t\t\t\t! material.isRawShaderMaterial ||\r\n\t\t\t\tmaterial.clipping === true ) {\r\n\r\n\t\t\t\tmaterialProperties.numClippingPlanes = _clipping.numPlanes;\r\n\t\t\t\tmaterialProperties.numIntersection = _clipping.numIntersection;\r\n\t\t\t\tuniforms.clippingPlanes = _clipping.uniform;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterialProperties.fog = fog;\r\n\r\n\t\t\t// store the light setup it was created for\r\n\r\n\t\t\tmaterialProperties.needsLights = materialNeedsLights( material );\r\n\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\r\n\r\n\t\t\tif ( materialProperties.needsLights ) {\r\n\r\n\t\t\t\t// wire up the material to this renderer's lighting state\r\n\r\n\t\t\t\tuniforms.ambientLightColor.value = lights.state.ambient;\r\n\t\t\t\tuniforms.lightProbe.value = lights.state.probe;\r\n\t\t\t\tuniforms.directionalLights.value = lights.state.directional;\r\n\t\t\t\tuniforms.spotLights.value = lights.state.spot;\r\n\t\t\t\tuniforms.rectAreaLights.value = lights.state.rectArea;\r\n\t\t\t\tuniforms.pointLights.value = lights.state.point;\r\n\t\t\t\tuniforms.hemisphereLights.value = lights.state.hemi;\r\n\r\n\t\t\t\tuniforms.directionalShadowMap.value = lights.state.directionalShadowMap;\r\n\t\t\t\tuniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;\r\n\t\t\t\tuniforms.spotShadowMap.value = lights.state.spotShadowMap;\r\n\t\t\t\tuniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;\r\n\t\t\t\tuniforms.pointShadowMap.value = lights.state.pointShadowMap;\r\n\t\t\t\tuniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;\r\n\t\t\t\t// TODO (abelnation): add area lights shadow info to uniforms\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar progUniforms = materialProperties.program.getUniforms(),\r\n\t\t\t\tuniformsList =\r\n\t\t\t\t\tWebGLUniforms.seqWithValue( progUniforms.seq, uniforms );\r\n\r\n\t\t\tmaterialProperties.uniformsList = uniformsList;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setProgram( camera, fog, material, object ) {\r\n\r\n\t\t\ttextures.resetTextureUnits();\r\n\r\n\t\t\tvar materialProperties = properties.get( material );\r\n\t\t\tvar lights = currentRenderState.state.lights;\r\n\r\n\t\t\tif ( _clippingEnabled ) {\r\n\r\n\t\t\t\tif ( _localClippingEnabled || camera !== _currentCamera ) {\r\n\r\n\t\t\t\t\tvar useCache =\r\n\t\t\t\t\t\tcamera === _currentCamera &&\r\n\t\t\t\t\t\tmaterial.id === _currentMaterialId;\r\n\r\n\t\t\t\t\t// we might want to call this function with some ClippingGroup\r\n\t\t\t\t\t// object instead of the material, once it becomes feasible\r\n\t\t\t\t\t// (#8465, #8379)\r\n\t\t\t\t\t_clipping.setState(\r\n\t\t\t\t\t\tmaterial.clippingPlanes, material.clipIntersection, material.clipShadows,\r\n\t\t\t\t\t\tcamera, materialProperties, useCache );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.version === materialProperties.__version ) {\r\n\r\n\t\t\t\tif ( materialProperties.program === undefined ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( material.fog && materialProperties.fog !== fog ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( materialProperties.numClippingPlanes !== undefined &&\r\n\t\t\t\t\t( materialProperties.numClippingPlanes !== _clipping.numPlanes ||\r\n\t\t\t\t\tmaterialProperties.numIntersection !== _clipping.numIntersection ) ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.version !== materialProperties.__version ) {\r\n\r\n\t\t\t\tinitMaterial( material, fog, object );\r\n\t\t\t\tmaterialProperties.__version = material.version;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar refreshProgram = false;\r\n\t\t\tvar refreshMaterial = false;\r\n\t\t\tvar refreshLights = false;\r\n\r\n\t\t\tvar program = materialProperties.program,\r\n\t\t\t\tp_uniforms = program.getUniforms(),\r\n\t\t\t\tm_uniforms = materialProperties.shader.uniforms;\r\n\r\n\t\t\tif ( state.useProgram( program.program ) ) {\r\n\r\n\t\t\t\trefreshProgram = true;\r\n\t\t\t\trefreshMaterial = true;\r\n\t\t\t\trefreshLights = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.id !== _currentMaterialId ) {\r\n\r\n\t\t\t\t_currentMaterialId = material.id;\r\n\r\n\t\t\t\trefreshMaterial = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshProgram || _currentCamera !== camera ) {\r\n\r\n\t\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\t\tmultiview.updateCameraProjectionMatricesUniform( camera, p_uniforms );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( capabilities.logarithmicDepthBuffer ) {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'logDepthBufFC',\r\n\t\t\t\t\t\t2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( _currentCamera !== camera ) {\r\n\r\n\t\t\t\t\t_currentCamera = camera;\r\n\r\n\t\t\t\t\t// lighting uniforms depend on the camera so enforce an update\r\n\t\t\t\t\t// now, in case this material supports lights - or later, when\r\n\t\t\t\t\t// the next material that does gets activated:\r\n\r\n\t\t\t\t\trefreshMaterial = true;\t\t// set to true on material change\r\n\t\t\t\t\trefreshLights = true;\t\t// remains set until update done\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// load material specific uniforms\r\n\t\t\t\t// (shader material also gets them for the sake of genericity)\r\n\r\n\t\t\t\tif ( material.isShaderMaterial ||\r\n\t\t\t\t\tmaterial.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.envMap ) {\r\n\r\n\t\t\t\t\tvar uCamPos = p_uniforms.map.cameraPosition;\r\n\r\n\t\t\t\t\tif ( uCamPos !== undefined ) {\r\n\r\n\t\t\t\t\t\tuCamPos.setValue( _gl,\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( camera.matrixWorld ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshLambertMaterial ||\r\n\t\t\t\t\tmaterial.isMeshBasicMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.isShaderMaterial ) {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshLambertMaterial ||\r\n\t\t\t\t\tmaterial.isMeshBasicMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.isShaderMaterial ||\r\n\t\t\t\t\tmaterial.skinning ) {\r\n\r\n\t\t\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\t\t\tmultiview.updateCameraViewMatricesUniform( camera, p_uniforms );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skinning uniforms must be set even if material didn't change\r\n\t\t\t// auto-setting of texture unit for bone texture must go before other textures\r\n\t\t\t// not sure why, but otherwise weird things happen\r\n\r\n\t\t\tif ( material.skinning ) {\r\n\r\n\t\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrix' );\r\n\t\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );\r\n\r\n\t\t\t\tvar skeleton = object.skeleton;\r\n\r\n\t\t\t\tif ( skeleton ) {\r\n\r\n\t\t\t\t\tvar bones = skeleton.bones;\r\n\r\n\t\t\t\t\tif ( capabilities.floatVertexTextures ) {\r\n\r\n\t\t\t\t\t\tif ( skeleton.boneTexture === undefined ) {\r\n\r\n\t\t\t\t\t\t\t// layout (1 matrix = 4 pixels)\r\n\t\t\t\t\t\t\t// RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)\r\n\t\t\t\t\t\t\t// with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)\r\n\t\t\t\t\t\t\t// 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)\r\n\t\t\t\t\t\t\t// 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)\r\n\t\t\t\t\t\t\t// 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)\r\n\r\n\r\n\t\t\t\t\t\t\tvar size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix\r\n\t\t\t\t\t\t\tsize = _Math.ceilPowerOfTwo( size );\r\n\t\t\t\t\t\t\tsize = Math.max( size, 4 );\r\n\r\n\t\t\t\t\t\t\tvar boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel\r\n\t\t\t\t\t\t\tboneMatrices.set( skeleton.boneMatrices ); // copy current values\r\n\r\n\t\t\t\t\t\t\tvar boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );\r\n\r\n\t\t\t\t\t\t\tskeleton.boneMatrices = boneMatrices;\r\n\t\t\t\t\t\t\tskeleton.boneTexture = boneTexture;\r\n\t\t\t\t\t\t\tskeleton.boneTextureSize = size;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tp_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {\r\n\r\n\t\t\t\tmaterialProperties.receiveShadow = object.receiveShadow;\r\n\t\t\t\tp_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshMaterial ) {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );\r\n\t\t\t\tp_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );\r\n\r\n\t\t\t\tif ( materialProperties.needsLights ) {\r\n\r\n\t\t\t\t\t// the current material requires lighting info\r\n\r\n\t\t\t\t\t// note: all lighting uniforms are always set correctly\r\n\t\t\t\t\t// they simply reference the renderer's state for their\r\n\t\t\t\t\t// values\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// use the current material's .needsUpdate flags to set\r\n\t\t\t\t\t// the GL state when required\r\n\r\n\t\t\t\t\tmarkUniformsLightsNeedsUpdate( m_uniforms, refreshLights );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// refresh uniforms common to several materials\r\n\r\n\t\t\t\tif ( fog && material.fog ) {\r\n\r\n\t\t\t\t\trefreshUniformsFog( m_uniforms, fog );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshBasicMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshLambertMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsLambert( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshToonMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsToon( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshPhongMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsPhong( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshStandardMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t\tif ( material.isMeshPhysicalMaterial ) {\r\n\r\n\t\t\t\t\t\trefreshUniformsPhysical( m_uniforms, material );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\trefreshUniformsStandard( m_uniforms, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( material.isMeshMatcapMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t\trefreshUniformsMatcap( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshDepthMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsDepth( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshDistanceMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsDistance( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshNormalMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsNormal( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isLineBasicMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsLine( m_uniforms, material );\r\n\r\n\t\t\t\t\tif ( material.isLineDashedMaterial ) {\r\n\r\n\t\t\t\t\t\trefreshUniformsDash( m_uniforms, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( material.isPointsMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsPoints( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isSpriteMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsSprites( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isShadowMaterial ) {\r\n\r\n\t\t\t\t\tm_uniforms.color.value.copy( material.color );\r\n\t\t\t\t\tm_uniforms.opacity.value = material.opacity;\r\n\r\n\t\t\t\t} else if ( material.envMap ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// RectAreaLight Texture\r\n\t\t\t\t// TODO (mrdoob): Find a nicer implementation\r\n\r\n\t\t\t\tif ( m_uniforms.ltc_1 !== undefined ) { m_uniforms.ltc_1.value = UniformsLib.LTC_1; }\r\n\t\t\t\tif ( m_uniforms.ltc_2 !== undefined ) { m_uniforms.ltc_2.value = UniformsLib.LTC_2; }\r\n\r\n\t\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\r\n\r\n\t\t\t\tif ( material.isShaderMaterial ) {\r\n\r\n\t\t\t\t\tmaterial.uniformsNeedUpdate = false; // #15581\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {\r\n\r\n\t\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\r\n\t\t\t\tmaterial.uniformsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.isSpriteMaterial ) {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'center', object.center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// common matrices\r\n\r\n\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\tmultiview.updateObjectMatricesUniforms( object, camera, p_uniforms );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );\r\n\t\t\t\tp_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );\r\n\r\n\t\t\treturn program;\r\n\r\n\t\t}\r\n\r\n\t\t// Uniforms (refresh uniforms objects)\r\n\r\n\t\tfunction refreshUniformsCommon( uniforms, material ) {\r\n\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\r\n\t\t\tif ( material.color ) {\r\n\r\n\t\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissive ) {\r\n\r\n\t\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.specularMap ) {\r\n\r\n\t\t\t\tuniforms.specularMap.value = material.specularMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.envMap ) {\r\n\r\n\t\t\t\tuniforms.envMap.value = material.envMap;\r\n\r\n\t\t\t\t// don't flip CubeTexture envMaps, flip everything else:\r\n\t\t\t\t// WebGLRenderTargetCube will be flipped for backwards compatibility\r\n\t\t\t\t// WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture\r\n\t\t\t\t// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future\r\n\t\t\t\tuniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;\r\n\r\n\t\t\t\tuniforms.reflectivity.value = material.reflectivity;\r\n\t\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\r\n\r\n\t\t\t\tuniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.lightMap ) {\r\n\r\n\t\t\t\tuniforms.lightMap.value = material.lightMap;\r\n\t\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.aoMap ) {\r\n\r\n\t\t\t\tuniforms.aoMap.value = material.aoMap;\r\n\t\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. specular map\r\n\t\t\t// 3. normal map\r\n\t\t\t// 4. bump map\r\n\t\t\t// 5. alpha map\r\n\t\t\t// 6. emissive map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.specularMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.specularMap;\r\n\r\n\t\t\t} else if ( material.displacementMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.displacementMap;\r\n\r\n\t\t\t} else if ( material.normalMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.normalMap;\r\n\r\n\t\t\t} else if ( material.bumpMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.bumpMap;\r\n\r\n\t\t\t} else if ( material.roughnessMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.roughnessMap;\r\n\r\n\t\t\t} else if ( material.metalnessMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.metalnessMap;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t} else if ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\t// backwards compatibility\r\n\t\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tuvScaleMap = uvScaleMap.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities for uv2\r\n\t\t\t// 1. ao map\r\n\t\t\t// 2. light map\r\n\r\n\t\t\tvar uv2ScaleMap;\r\n\r\n\t\t\tif ( material.aoMap ) {\r\n\r\n\t\t\t\tuv2ScaleMap = material.aoMap;\r\n\r\n\t\t\t} else if ( material.lightMap ) {\r\n\r\n\t\t\t\tuv2ScaleMap = material.lightMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv2ScaleMap !== undefined ) {\r\n\r\n\t\t\t\t// backwards compatibility\r\n\t\t\t\tif ( uv2ScaleMap.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tuv2ScaleMap = uv2ScaleMap.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uv2ScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuv2ScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsLine( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDash( uniforms, material ) {\r\n\r\n\t\t\tuniforms.dashSize.value = material.dashSize;\r\n\t\t\tuniforms.totalSize.value = material.dashSize + material.gapSize;\r\n\t\t\tuniforms.scale.value = material.scale;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPoints( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\t\t\tuniforms.size.value = material.size * _pixelRatio;\r\n\t\t\tuniforms.scale.value = _height * 0.5;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. alpha map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsSprites( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\t\t\tuniforms.rotation.value = material.rotation;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. alpha map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsFog( uniforms, fog ) {\r\n\r\n\t\t\tuniforms.fogColor.value.copy( fog.color );\r\n\r\n\t\t\tif ( fog.isFog ) {\r\n\r\n\t\t\t\tuniforms.fogNear.value = fog.near;\r\n\t\t\t\tuniforms.fogFar.value = fog.far;\r\n\r\n\t\t\t} else if ( fog.isFogExp2 ) {\r\n\r\n\t\t\t\tuniforms.fogDensity.value = fog.density;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsLambert( uniforms, material ) {\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPhong( uniforms, material ) {\r\n\r\n\t\t\tuniforms.specular.value.copy( material.specular );\r\n\t\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsToon( uniforms, material ) {\r\n\r\n\t\t\tuniforms.specular.value.copy( material.specular );\r\n\t\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\r\n\r\n\t\t\tif ( material.gradientMap ) {\r\n\r\n\t\t\t\tuniforms.gradientMap.value = material.gradientMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsStandard( uniforms, material ) {\r\n\r\n\t\t\tuniforms.roughness.value = material.roughness;\r\n\t\t\tuniforms.metalness.value = material.metalness;\r\n\r\n\t\t\tif ( material.roughnessMap ) {\r\n\r\n\t\t\t\tuniforms.roughnessMap.value = material.roughnessMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.metalnessMap ) {\r\n\r\n\t\t\t\tuniforms.metalnessMap.value = material.metalnessMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.envMap ) {\r\n\r\n\t\t\t\t//uniforms.envMap.value = material.envMap; // part of uniforms common\r\n\t\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPhysical( uniforms, material ) {\r\n\r\n\t\t\trefreshUniformsStandard( uniforms, material );\r\n\r\n\t\t\tuniforms.reflectivity.value = material.reflectivity; // also part of uniforms common\r\n\r\n\t\t\tuniforms.clearcoat.value = material.clearcoat;\r\n\t\t\tuniforms.clearcoatRoughness.value = material.clearcoatRoughness;\r\n\t\t\tif ( material.sheen ) { uniforms.sheen.value.copy( material.sheen ); }\r\n\r\n\t\t\tif ( material.clearcoatNormalMap ) {\r\n\r\n\t\t\t\tuniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );\r\n\t\t\t\tuniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;\r\n\r\n\t\t\t\tif ( material.side === BackSide ) {\r\n\r\n\t\t\t\t\tuniforms.clearcoatNormalScale.value.negate();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.transparency.value = material.transparency;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsMatcap( uniforms, material ) {\r\n\r\n\t\t\tif ( material.matcap ) {\r\n\r\n\t\t\t\tuniforms.matcap.value = material.matcap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDepth( uniforms, material ) {\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDistance( uniforms, material ) {\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.referencePosition.value.copy( material.referencePosition );\r\n\t\t\tuniforms.nearDistance.value = material.nearDistance;\r\n\t\t\tuniforms.farDistance.value = material.farDistance;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsNormal( uniforms, material ) {\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// If uniforms are marked as clean, they don't need to be loaded to the GPU.\r\n\r\n\t\tfunction markUniformsLightsNeedsUpdate( uniforms, value ) {\r\n\r\n\t\t\tuniforms.ambientLightColor.needsUpdate = value;\r\n\t\t\tuniforms.lightProbe.needsUpdate = value;\r\n\r\n\t\t\tuniforms.directionalLights.needsUpdate = value;\r\n\t\t\tuniforms.pointLights.needsUpdate = value;\r\n\t\t\tuniforms.spotLights.needsUpdate = value;\r\n\t\t\tuniforms.rectAreaLights.needsUpdate = value;\r\n\t\t\tuniforms.hemisphereLights.needsUpdate = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction materialNeedsLights( material ) {\r\n\r\n\t\t\treturn material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||\r\n\t\t\t\tmaterial.isMeshStandardMaterial || material.isShadowMaterial ||\r\n\t\t\t\t( material.isShaderMaterial && material.lights === true );\r\n\r\n\t\t}\r\n\r\n\t\t// this.setTexture2D = setTexture2D;\r\n\t\tthis.setTexture2D = ( function () {\r\n\r\n\t\t\tvar warned = false;\r\n\r\n\t\t\t// backwards compatibility: peel texture.texture\r\n\t\t\treturn function setTexture2D( texture, slot ) {\r\n\r\n\t\t\t\tif ( texture && texture.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tif ( ! warned ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( \"THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\t\twarned = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextures.setTexture2D( texture, slot );\r\n\r\n\t\t\t};\r\n\r\n\t\t}() );\r\n\r\n\t\t//\r\n\t\tthis.setFramebuffer = function ( value ) {\r\n\r\n\t\t\tif ( _framebuffer !== value && _currentRenderTarget === null ) { _gl.bindFramebuffer( 36160, value ); }\r\n\r\n\t\t\t_framebuffer = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getActiveCubeFace = function () {\r\n\r\n\t\t\treturn _currentActiveCubeFace;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getActiveMipmapLevel = function () {\r\n\r\n\t\t\treturn _currentActiveMipmapLevel;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getRenderTarget = function () {\r\n\r\n\t\t\treturn _currentRenderTarget;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipmapLevel ) {\r\n\r\n\t\t\t_currentRenderTarget = renderTarget;\r\n\t\t\t_currentActiveCubeFace = activeCubeFace;\r\n\t\t\t_currentActiveMipmapLevel = activeMipmapLevel;\r\n\r\n\t\t\tif ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {\r\n\r\n\t\t\t\ttextures.setupRenderTarget( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar framebuffer = _framebuffer;\r\n\t\t\tvar isCube = false;\r\n\r\n\t\t\tif ( renderTarget ) {\r\n\r\n\t\t\t\tvar __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;\r\n\r\n\t\t\t\tif ( renderTarget.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\t\tframebuffer = __webglFramebuffer[ activeCubeFace || 0 ];\r\n\t\t\t\t\tisCube = true;\r\n\r\n\t\t\t\t} else if ( renderTarget.isWebGLMultisampleRenderTarget ) {\r\n\r\n\t\t\t\t\tframebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tframebuffer = __webglFramebuffer;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_currentViewport.copy( renderTarget.viewport );\r\n\t\t\t\t_currentScissor.copy( renderTarget.scissor );\r\n\t\t\t\t_currentScissorTest = renderTarget.scissorTest;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();\r\n\t\t\t\t_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();\r\n\t\t\t\t_currentScissorTest = _scissorTest;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _currentFramebuffer !== framebuffer ) {\r\n\r\n\t\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\t\t\t\t_currentFramebuffer = framebuffer;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.viewport( _currentViewport );\r\n\t\t\tstate.scissor( _currentScissor );\r\n\t\t\tstate.setScissorTest( _currentScissorTest );\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 36064, 34069 + ( activeCubeFace || 0 ), textureProperties.__webglTexture, activeMipmapLevel || 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {\r\n\r\n\t\t\tif ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar framebuffer = properties.get( renderTarget ).__webglFramebuffer;\r\n\r\n\t\t\tif ( renderTarget.isWebGLRenderTargetCube && activeCubeFaceIndex !== undefined ) {\r\n\r\n\t\t\t\tframebuffer = framebuffer[ activeCubeFaceIndex ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( framebuffer ) {\r\n\r\n\t\t\t\tvar restore = false;\r\n\r\n\t\t\t\tif ( framebuffer !== _currentFramebuffer ) {\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\r\n\t\t\t\t\trestore = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tvar texture = renderTarget.texture;\r\n\t\t\t\t\tvar textureFormat = texture.format;\r\n\t\t\t\t\tvar textureType = texture.type;\r\n\r\n\t\t\t\t\tif ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)\r\n\t\t\t\t\t\t! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox\r\n\t\t\t\t\t\t! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {\r\n\r\n\t\t\t\t\t\t// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)\r\n\r\n\t\t\t\t\t\tif ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {\r\n\r\n\t\t\t\t\t\t\t_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} finally {\r\n\r\n\t\t\t\t\tif ( restore ) {\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, _currentFramebuffer );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.copyFramebufferToTexture = function ( position, texture, level ) {\r\n\r\n\t\t\tif ( level === undefined ) { level = 0; }\r\n\r\n\t\t\tvar levelScale = Math.pow( 2, - level );\r\n\t\t\tvar width = Math.floor( texture.image.width * levelScale );\r\n\t\t\tvar height = Math.floor( texture.image.height * levelScale );\r\n\t\t\tvar glFormat = utils.convert( texture.format );\r\n\r\n\t\t\ttextures.setTexture2D( texture, 0 );\r\n\r\n\t\t\t_gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tthis.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {\r\n\r\n\t\t\tvar width = srcTexture.image.width;\r\n\t\t\tvar height = srcTexture.image.height;\r\n\t\t\tvar glFormat = utils.convert( dstTexture.format );\r\n\t\t\tvar glType = utils.convert( dstTexture.type );\r\n\r\n\t\t\ttextures.setTexture2D( dstTexture, 0 );\r\n\r\n\t\t\tif ( srcTexture.isDataTexture ) {\r\n\r\n\t\t\t\t_gl.texSubImage2D( 3553, level || 0, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.texSubImage2D( 3553, level || 0, position.x, position.y, glFormat, glType, srcTexture.image );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tthis.initTexture = function ( texture ) {\r\n\r\n\t\t\ttextures.setTexture2D( texture, 0 );\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction FogExp2( color, density ) {\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.color = new Color( color );\r\n\t\tthis.density = ( density !== undefined ) ? density : 0.00025;\r\n\r\n\t}\r\n\r\n\tObject.assign( FogExp2.prototype, {\r\n\r\n\t\tisFogExp2: true,\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new FogExp2( this.color, this.density );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( /* meta */ ) {\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttype: 'FogExp2',\r\n\t\t\t\tcolor: this.color.getHex(),\r\n\t\t\t\tdensity: this.density\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Fog( color, near, far ) {\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.color = new Color( color );\r\n\r\n\t\tthis.near = ( near !== undefined ) ? near : 1;\r\n\t\tthis.far = ( far !== undefined ) ? far : 1000;\r\n\r\n\t}\r\n\r\n\tObject.assign( Fog.prototype, {\r\n\r\n\t\tisFog: true,\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Fog( this.color, this.near, this.far );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( /* meta */ ) {\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttype: 'Fog',\r\n\t\t\t\tcolor: this.color.getHex(),\r\n\t\t\t\tnear: this.near,\r\n\t\t\t\tfar: this.far\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InterleavedBuffer( array, stride ) {\r\n\r\n\t\tthis.array = array;\r\n\t\tthis.stride = stride;\r\n\t\tthis.count = array !== undefined ? array.length / stride : 0;\r\n\r\n\t\tthis.usage = StaticDrawUsage;\r\n\t\tthis.updateRange = { offset: 0, count: - 1 };\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBuffer.prototype, {\r\n\r\n\t\tisInterleavedBuffer: true,\r\n\r\n\t\tonUploadCallback: function () {},\r\n\r\n\t\tsetUsage: function ( value ) {\r\n\r\n\t\t\tthis.usage = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.array = new source.array.constructor( source.array );\r\n\t\t\tthis.count = source.count;\r\n\t\t\tthis.stride = source.stride;\r\n\t\t\tthis.usage = source.usage;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyAt: function ( index1, attribute, index2 ) {\r\n\r\n\t\t\tindex1 *= this.stride;\r\n\t\t\tindex2 *= attribute.stride;\r\n\r\n\t\t\tfor ( var i = 0, l = this.stride; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.array.set( value, offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tonUpload: function ( callback ) {\r\n\r\n\t\t\tthis.onUploadCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {\r\n\r\n\t\tthis.data = interleavedBuffer;\r\n\t\tthis.itemSize = itemSize;\r\n\t\tthis.offset = offset;\r\n\r\n\t\tthis.normalized = normalized === true;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( InterleavedBufferAttribute.prototype, {\r\n\r\n\t\tcount: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.data.count;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tarray: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.data.array;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBufferAttribute.prototype, {\r\n\r\n\t\tisInterleavedBufferAttribute: true,\r\n\r\n\t\tsetX: function ( index, x ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset ] = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( index, y ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( index, z ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( index, w ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetX: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset ];\r\n\r\n\t\t},\r\n\r\n\t\tgetY: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 1 ];\r\n\r\n\t\t},\r\n\r\n\t\tgetZ: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 2 ];\r\n\r\n\t\t},\r\n\r\n\t\tgetW: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 3 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetXY: function ( index, x, y ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZ: function ( index, x, y, z ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\t\t\tthis.data.array[ index + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZW: function ( index, x, y, z, w ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\t\t\tthis.data.array[ index + 2 ] = z;\r\n\t\t\tthis.data.array[ index + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * map: new THREE.Texture( ),\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t * rotation: ,\r\n\t * sizeAttenuation: \r\n\t * }\r\n\t */\r\n\r\n\tfunction SpriteMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'SpriteMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.rotation = 0;\r\n\r\n\t\tthis.sizeAttenuation = true;\r\n\r\n\t\tthis.transparent = true;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tSpriteMaterial.prototype = Object.create( Material.prototype );\r\n\tSpriteMaterial.prototype.constructor = SpriteMaterial;\r\n\tSpriteMaterial.prototype.isSpriteMaterial = true;\r\n\r\n\tSpriteMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.rotation = source.rotation;\r\n\r\n\t\tthis.sizeAttenuation = source.sizeAttenuation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar _geometry;\r\n\r\n\tvar _intersectPoint = new Vector3();\r\n\tvar _worldScale = new Vector3();\r\n\tvar _mvPosition = new Vector3();\r\n\r\n\tvar _alignedPosition = new Vector2();\r\n\tvar _rotatedPosition = new Vector2();\r\n\tvar _viewWorldMatrix = new Matrix4();\r\n\r\n\tvar _vA$1 = new Vector3();\r\n\tvar _vB$1 = new Vector3();\r\n\tvar _vC$1 = new Vector3();\r\n\r\n\tvar _uvA$1 = new Vector2();\r\n\tvar _uvB$1 = new Vector2();\r\n\tvar _uvC$1 = new Vector2();\r\n\r\n\tfunction Sprite( material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Sprite';\r\n\r\n\t\tif ( _geometry === undefined ) {\r\n\r\n\t\t\t_geometry = new BufferGeometry();\r\n\r\n\t\t\tvar float32Array = new Float32Array( [\r\n\t\t\t\t- 0.5, - 0.5, 0, 0, 0,\r\n\t\t\t\t0.5, - 0.5, 0, 1, 0,\r\n\t\t\t\t0.5, 0.5, 0, 1, 1,\r\n\t\t\t\t- 0.5, 0.5, 0, 0, 1\r\n\t\t\t] );\r\n\r\n\t\t\tvar interleavedBuffer = new InterleavedBuffer( float32Array, 5 );\r\n\r\n\t\t\t_geometry.setIndex( [ 0, 1, 2,\t0, 2, 3 ] );\r\n\t\t\t_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );\r\n\t\t\t_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );\r\n\r\n\t\t}\r\n\r\n\t\tthis.geometry = _geometry;\r\n\t\tthis.material = ( material !== undefined ) ? material : new SpriteMaterial();\r\n\r\n\t\tthis.center = new Vector2( 0.5, 0.5 );\r\n\r\n\t}\r\n\r\n\tSprite.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Sprite,\r\n\r\n\t\tisSprite: true,\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tif ( raycaster.camera === null ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Sprite: \"Raycaster.camera\" needs to be set in order to raycast against sprites.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_worldScale.setFromMatrixScale( this.matrixWorld );\r\n\r\n\t\t\t_viewWorldMatrix.copy( raycaster.camera.matrixWorld );\r\n\t\t\tthis.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );\r\n\r\n\t\t\t_mvPosition.setFromMatrixPosition( this.modelViewMatrix );\r\n\r\n\t\t\tif ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {\r\n\r\n\t\t\t\t_worldScale.multiplyScalar( - _mvPosition.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar rotation = this.material.rotation;\r\n\t\t\tvar sin, cos;\r\n\t\t\tif ( rotation !== 0 ) {\r\n\r\n\t\t\t\tcos = Math.cos( rotation );\r\n\t\t\t\tsin = Math.sin( rotation );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar center = this.center;\r\n\r\n\t\t\ttransformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\ttransformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\ttransformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\r\n\t\t\t_uvA$1.set( 0, 0 );\r\n\t\t\t_uvB$1.set( 1, 0 );\r\n\t\t\t_uvC$1.set( 1, 1 );\r\n\r\n\t\t\t// check first triangle\r\n\t\t\tvar intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );\r\n\r\n\t\t\tif ( intersect === null ) {\r\n\r\n\t\t\t\t// check second triangle\r\n\t\t\t\ttransformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\t\t_uvB$1.set( 0, 1 );\r\n\r\n\t\t\t\tintersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );\r\n\t\t\t\tif ( intersect === null ) {\r\n\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar distance = raycaster.ray.origin.distanceTo( _intersectPoint );\r\n\r\n\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return; }\r\n\r\n\t\t\tintersects.push( {\r\n\r\n\t\t\t\tdistance: distance,\r\n\t\t\t\tpoint: _intersectPoint.clone(),\r\n\t\t\t\tuv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),\r\n\t\t\t\tface: null,\r\n\t\t\t\tobject: this\r\n\r\n\t\t\t} );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.material ).copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tif ( source.center !== undefined ) { this.center.copy( source.center ); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\r\n\t} );\r\n\r\n\tfunction transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {\r\n\r\n\t\t// compute position in camera space\r\n\t\t_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );\r\n\r\n\t\t// to check if rotation is not zero\r\n\t\tif ( sin !== undefined ) {\r\n\r\n\t\t\t_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );\r\n\t\t\t_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t_rotatedPosition.copy( _alignedPosition );\r\n\r\n\t\t}\r\n\r\n\r\n\t\tvertexPosition.copy( mvPosition );\r\n\t\tvertexPosition.x += _rotatedPosition.x;\r\n\t\tvertexPosition.y += _rotatedPosition.y;\r\n\r\n\t\t// transform to world space\r\n\t\tvertexPosition.applyMatrix4( _viewWorldMatrix );\r\n\r\n\t}\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _v1$4 = new Vector3();\r\n\tvar _v2$2 = new Vector3();\r\n\r\n\tfunction LOD() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'LOD';\r\n\r\n\t\tObject.defineProperties( this, {\r\n\t\t\tlevels: {\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: []\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.autoUpdate = true;\r\n\r\n\t}\r\n\r\n\tLOD.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: LOD,\r\n\r\n\t\tisLOD: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, false );\r\n\r\n\t\t\tvar levels = source.levels;\r\n\r\n\t\t\tfor ( var i = 0, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar level = levels[ i ];\r\n\r\n\t\t\t\tthis.addLevel( level.object.clone(), level.distance );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.autoUpdate = source.autoUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddLevel: function ( object, distance ) {\r\n\r\n\t\t\tif ( distance === undefined ) { distance = 0; }\r\n\r\n\t\t\tdistance = Math.abs( distance );\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tfor ( var l = 0; l < levels.length; l ++ ) {\r\n\r\n\t\t\t\tif ( distance < levels[ l ].distance ) {\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tlevels.splice( l, 0, { distance: distance, object: object } );\r\n\r\n\t\t\tthis.add( object );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectForDistance: function ( distance ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 0 ) {\r\n\r\n\t\t\t\tfor ( var i = 1, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tif ( distance < levels[ i ].distance ) {\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn levels[ i - 1 ].object;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 0 ) {\r\n\r\n\t\t\t\t_v1$4.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( _v1$4 );\r\n\r\n\t\t\t\tthis.getObjectForDistance( distance ).raycast( raycaster, intersects );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdate: function ( camera ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 1 ) {\r\n\r\n\t\t\t\t_v1$4.setFromMatrixPosition( camera.matrixWorld );\r\n\t\t\t\t_v2$2.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\t\tvar distance = _v1$4.distanceTo( _v2$2 );\r\n\r\n\t\t\t\tlevels[ 0 ].object.visible = true;\r\n\r\n\t\t\t\tfor ( var i = 1, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tif ( distance >= levels[ i ].distance ) {\r\n\r\n\t\t\t\t\t\tlevels[ i - 1 ].object.visible = false;\r\n\t\t\t\t\t\tlevels[ i ].object.visible = true;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( ; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tlevels[ i ].object.visible = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tif ( this.autoUpdate === false ) { data.object.autoUpdate = false; }\r\n\r\n\t\t\tdata.object.levels = [];\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tfor ( var i = 0, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar level = levels[ i ];\r\n\r\n\t\t\t\tdata.object.levels.push( {\r\n\t\t\t\t\tobject: level.object.uuid,\r\n\t\t\t\t\tdistance: level.distance\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tfunction SkinnedMesh( geometry, material ) {\r\n\r\n\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t}\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'SkinnedMesh';\r\n\r\n\t\tthis.bindMode = 'attached';\r\n\t\tthis.bindMatrix = new Matrix4();\r\n\t\tthis.bindMatrixInverse = new Matrix4();\r\n\r\n\t}\r\n\r\n\tSkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {\r\n\r\n\t\tconstructor: SkinnedMesh,\r\n\r\n\t\tisSkinnedMesh: true,\r\n\r\n\t\tbind: function ( skeleton, bindMatrix ) {\r\n\r\n\t\t\tthis.skeleton = skeleton;\r\n\r\n\t\t\tif ( bindMatrix === undefined ) {\r\n\r\n\t\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\t\tthis.skeleton.calculateInverses();\r\n\r\n\t\t\t\tbindMatrix = this.matrixWorld;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.bindMatrix.copy( bindMatrix );\r\n\t\t\tthis.bindMatrixInverse.getInverse( bindMatrix );\r\n\r\n\t\t},\r\n\r\n\t\tpose: function () {\r\n\r\n\t\t\tthis.skeleton.pose();\r\n\r\n\t\t},\r\n\r\n\t\tnormalizeSkinWeights: function () {\r\n\r\n\t\t\tvar vector = new Vector4();\r\n\r\n\t\t\tvar skinWeight = this.geometry.attributes.skinWeight;\r\n\r\n\t\t\tfor ( var i = 0, l = skinWeight.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvector.x = skinWeight.getX( i );\r\n\t\t\t\tvector.y = skinWeight.getY( i );\r\n\t\t\t\tvector.z = skinWeight.getZ( i );\r\n\t\t\t\tvector.w = skinWeight.getW( i );\r\n\r\n\t\t\t\tvar scale = 1.0 / vector.manhattanLength();\r\n\r\n\t\t\t\tif ( scale !== Infinity ) {\r\n\r\n\t\t\t\t\tvector.multiplyScalar( scale );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvector.set( 1, 0, 0, 0 ); // do something reasonable\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tskinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tMesh.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tif ( this.bindMode === 'attached' ) {\r\n\r\n\t\t\t\tthis.bindMatrixInverse.getInverse( this.matrixWorld );\r\n\r\n\t\t\t} else if ( this.bindMode === 'detached' ) {\r\n\r\n\t\t\t\tthis.bindMatrixInverse.getInverse( this.bindMatrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author michael guerrero / http://realitymeltdown.com\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tvar _offsetMatrix = new Matrix4();\r\n\tvar _identityMatrix = new Matrix4();\r\n\r\n\tfunction Skeleton( bones, boneInverses ) {\r\n\r\n\t\t// copy the bone array\r\n\r\n\t\tbones = bones || [];\r\n\r\n\t\tthis.bones = bones.slice( 0 );\r\n\t\tthis.boneMatrices = new Float32Array( this.bones.length * 16 );\r\n\r\n\t\tthis.frame = - 1;\r\n\r\n\t\t// use the supplied bone inverses or calculate the inverses\r\n\r\n\t\tif ( boneInverses === undefined ) {\r\n\r\n\t\t\tthis.calculateInverses();\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( this.bones.length === boneInverses.length ) {\r\n\r\n\t\t\t\tthis.boneInverses = boneInverses.slice( 0 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Skeleton boneInverses is the wrong length.' );\r\n\r\n\t\t\t\tthis.boneInverses = [];\r\n\r\n\t\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tthis.boneInverses.push( new Matrix4() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Skeleton.prototype, {\r\n\r\n\t\tcalculateInverses: function () {\r\n\r\n\t\t\tthis.boneInverses = [];\r\n\r\n\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar inverse = new Matrix4();\r\n\r\n\t\t\t\tif ( this.bones[ i ] ) {\r\n\r\n\t\t\t\t\tinverse.getInverse( this.bones[ i ].matrixWorld );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.boneInverses.push( inverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tpose: function () {\r\n\r\n\t\t\tvar bone, i, il;\r\n\r\n\t\t\t// recover the bind-time world matrices\r\n\r\n\t\t\tfor ( i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tbone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone ) {\r\n\r\n\t\t\t\t\tbone.matrixWorld.getInverse( this.boneInverses[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// compute the local matrices, positions, rotations and scales\r\n\r\n\t\t\tfor ( i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tbone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone ) {\r\n\r\n\t\t\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\t\t\tbone.matrix.getInverse( bone.parent.matrixWorld );\r\n\t\t\t\t\t\tbone.matrix.multiply( bone.matrixWorld );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tbone.matrix.copy( bone.matrixWorld );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdate: function () {\r\n\r\n\t\t\tvar bones = this.bones;\r\n\t\t\tvar boneInverses = this.boneInverses;\r\n\t\t\tvar boneMatrices = this.boneMatrices;\r\n\t\t\tvar boneTexture = this.boneTexture;\r\n\r\n\t\t\t// flatten bone matrices to array\r\n\r\n\t\t\tfor ( var i = 0, il = bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// compute the offset between the current and the original transform\r\n\r\n\t\t\t\tvar matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;\r\n\r\n\t\t\t\t_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );\r\n\t\t\t\t_offsetMatrix.toArray( boneMatrices, i * 16 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( boneTexture !== undefined ) {\r\n\r\n\t\t\t\tboneTexture.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Skeleton( this.bones, this.boneInverses );\r\n\r\n\t\t},\r\n\r\n\t\tgetBoneByName: function ( name ) {\r\n\r\n\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar bone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone.name === name ) {\r\n\r\n\t\t\t\t\treturn bone;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tfunction Bone() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Bone';\r\n\r\n\t}\r\n\r\n\tBone.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Bone,\r\n\r\n\t\tisBone: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _instanceLocalMatrix = new Matrix4();\r\n\tvar _instanceWorldMatrix = new Matrix4();\r\n\r\n\tvar _instanceIntersects = [];\r\n\r\n\tvar _mesh = new Mesh();\r\n\r\n\tfunction InstancedMesh( geometry, material, count ) {\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );\r\n\r\n\t\tthis.count = count;\r\n\r\n\t}\r\n\r\n\tInstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {\r\n\r\n\t\tconstructor: InstancedMesh,\r\n\r\n\t\tisInstancedMesh: true,\r\n\r\n\t\tgetMatrixAt: function ( index, matrix ) {\r\n\r\n\t\t\tmatrix.fromArray( this.instanceMatrix.array, index * 16 );\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\t\t\tvar raycastTimes = this.count;\r\n\r\n\t\t\t_mesh.geometry = this.geometry;\r\n\t\t\t_mesh.material = this.material;\r\n\r\n\t\t\tif ( _mesh.material === undefined ) { return; }\r\n\r\n\t\t\tfor ( var instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {\r\n\r\n\t\t\t\t// calculate the world matrix for each instance\r\n\r\n\t\t\t\tthis.getMatrixAt( instanceId, _instanceLocalMatrix );\r\n\r\n\t\t\t\t_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );\r\n\r\n\t\t\t\t// the mesh represents this single instance\r\n\r\n\t\t\t\t_mesh.matrixWorld = _instanceWorldMatrix;\r\n\r\n\t\t\t\t_mesh.raycast( raycaster, _instanceIntersects );\r\n\r\n\t\t\t\t// process the result of raycast\r\n\r\n\t\t\t\tif ( _instanceIntersects.length > 0 ) {\r\n\r\n\t\t\t\t\t_instanceIntersects[ 0 ].instanceId = instanceId;\r\n\t\t\t\t\t_instanceIntersects[ 0 ].object = this;\r\n\r\n\t\t\t\t\tintersects.push( _instanceIntersects[ 0 ] );\r\n\r\n\t\t\t\t\t_instanceIntersects.length = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tsetMatrixAt: function ( index, matrix ) {\r\n\r\n\t\t\tmatrix.toArray( this.instanceMatrix.array, index * 16 );\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * linewidth: ,\r\n\t * linecap: \"round\",\r\n\t * linejoin: \"round\"\r\n\t * }\r\n\t */\r\n\r\n\tfunction LineBasicMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'LineBasicMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.linewidth = 1;\r\n\t\tthis.linecap = 'round';\r\n\t\tthis.linejoin = 'round';\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tLineBasicMaterial.prototype = Object.create( Material.prototype );\r\n\tLineBasicMaterial.prototype.constructor = LineBasicMaterial;\r\n\r\n\tLineBasicMaterial.prototype.isLineBasicMaterial = true;\r\n\r\n\tLineBasicMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.linewidth = source.linewidth;\r\n\t\tthis.linecap = source.linecap;\r\n\t\tthis.linejoin = source.linejoin;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _start = new Vector3();\r\n\tvar _end = new Vector3();\r\n\tvar _inverseMatrix$1 = new Matrix4();\r\n\tvar _ray$1 = new Ray();\r\n\tvar _sphere$2 = new Sphere();\r\n\r\n\tfunction Line( geometry, material, mode ) {\r\n\r\n\t\tif ( mode === 1 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );\r\n\r\n\t\t}\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Line';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t}\r\n\r\n\tLine.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Line,\r\n\r\n\t\tisLine: true,\r\n\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t// we assume non-indexed geometry\r\n\r\n\t\t\t\tif ( geometry.index === null ) {\r\n\r\n\t\t\t\t\tvar positionAttribute = geometry.attributes.position;\r\n\t\t\t\t\tvar lineDistances = [ 0 ];\r\n\r\n\t\t\t\t\tfor ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t_start.fromBufferAttribute( positionAttribute, i - 1 );\r\n\t\t\t\t\t\t_end.fromBufferAttribute( positionAttribute, i );\r\n\r\n\t\t\t\t\t\tlineDistances[ i ] = lineDistances[ i - 1 ];\r\n\t\t\t\t\t\tlineDistances[ i ] += _start.distanceTo( _end );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar lineDistances = geometry.lineDistances;\r\n\r\n\t\t\t\tlineDistances[ 0 ] = 0;\r\n\r\n\t\t\t\tfor ( var i = 1, l = vertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tlineDistances[ i ] = lineDistances[ i - 1 ];\r\n\t\t\t\t\tlineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar precision = raycaster.linePrecision;\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$2.copy( geometry.boundingSphere );\r\n\t\t\t_sphere$2.applyMatrix4( matrixWorld );\r\n\t\t\t_sphere$2.radius += precision;\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix$1.getInverse( matrixWorld );\r\n\t\t\t_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );\r\n\r\n\t\t\tvar localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );\r\n\t\t\tvar localPrecisionSq = localPrecision * localPrecision;\r\n\r\n\t\t\tvar vStart = new Vector3();\r\n\t\t\tvar vEnd = new Vector3();\r\n\t\t\tvar interSegment = new Vector3();\r\n\t\t\tvar interRay = new Vector3();\r\n\t\t\tvar step = ( this && this.isLineSegments ) ? 2 : 1;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar attributes = geometry.attributes;\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = indices.length - 1; i < l; i += step ) {\r\n\r\n\t\t\t\t\t\tvar a = indices[ i ];\r\n\t\t\t\t\t\tvar b = indices[ i + 1 ];\r\n\r\n\t\t\t\t\t\tvStart.fromArray( positions, a * 3 );\r\n\t\t\t\t\t\tvEnd.fromArray( positions, b * 3 );\r\n\r\n\t\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );\r\n\r\n\t\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {\r\n\r\n\t\t\t\t\t\tvStart.fromArray( positions, 3 * i );\r\n\t\t\t\t\t\tvEnd.fromArray( positions, 3 * i + 3 );\r\n\r\n\t\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );\r\n\r\n\t\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar nbVertices = vertices.length;\r\n\r\n\t\t\t\tfor ( var i = 0; i < nbVertices - 1; i += step ) {\r\n\r\n\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );\r\n\r\n\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _start$1 = new Vector3();\r\n\tvar _end$1 = new Vector3();\r\n\r\n\tfunction LineSegments( geometry, material ) {\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'LineSegments';\r\n\r\n\t}\r\n\r\n\tLineSegments.prototype = Object.assign( Object.create( Line.prototype ), {\r\n\r\n\t\tconstructor: LineSegments,\r\n\r\n\t\tisLineSegments: true,\r\n\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t// we assume non-indexed geometry\r\n\r\n\t\t\t\tif ( geometry.index === null ) {\r\n\r\n\t\t\t\t\tvar positionAttribute = geometry.attributes.position;\r\n\t\t\t\t\tvar lineDistances = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {\r\n\r\n\t\t\t\t\t\t_start$1.fromBufferAttribute( positionAttribute, i );\r\n\t\t\t\t\t\t_end$1.fromBufferAttribute( positionAttribute, i + 1 );\r\n\r\n\t\t\t\t\t\tlineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];\r\n\t\t\t\t\t\tlineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar lineDistances = geometry.lineDistances;\r\n\r\n\t\t\t\tfor ( var i = 0, l = vertices.length; i < l; i += 2 ) {\r\n\r\n\t\t\t\t\t_start$1.copy( vertices[ i ] );\r\n\t\t\t\t\t_end$1.copy( vertices[ i + 1 ] );\r\n\r\n\t\t\t\t\tlineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];\r\n\t\t\t\t\tlineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mgreter / http://github.com/mgreter\r\n\t */\r\n\r\n\tfunction LineLoop( geometry, material ) {\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'LineLoop';\r\n\r\n\t}\r\n\r\n\tLineLoop.prototype = Object.assign( Object.create( Line.prototype ), {\r\n\r\n\t\tconstructor: LineLoop,\r\n\r\n\t\tisLineLoop: true,\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t * map: new THREE.Texture( ),\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * size: ,\r\n\t * sizeAttenuation: \r\n\t *\r\n\t * morphTargets: \r\n\t * }\r\n\t */\r\n\r\n\tfunction PointsMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'PointsMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.size = 1;\r\n\t\tthis.sizeAttenuation = true;\r\n\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tPointsMaterial.prototype = Object.create( Material.prototype );\r\n\tPointsMaterial.prototype.constructor = PointsMaterial;\r\n\r\n\tPointsMaterial.prototype.isPointsMaterial = true;\r\n\r\n\tPointsMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.size = source.size;\r\n\t\tthis.sizeAttenuation = source.sizeAttenuation;\r\n\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar _inverseMatrix$2 = new Matrix4();\r\n\tvar _ray$2 = new Ray();\r\n\tvar _sphere$3 = new Sphere();\r\n\tvar _position$1 = new Vector3();\r\n\r\n\tfunction Points( geometry, material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Points';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t\tthis.updateMorphTargets();\r\n\r\n\t}\r\n\r\n\tPoints.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Points,\r\n\r\n\t\tisPoints: true,\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\t\t\tvar threshold = raycaster.params.Points.threshold;\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$3.copy( geometry.boundingSphere );\r\n\t\t\t_sphere$3.applyMatrix4( matrixWorld );\r\n\t\t\t_sphere$3.radius += threshold;\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix$2.getInverse( matrixWorld );\r\n\t\t\t_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );\r\n\r\n\t\t\tvar localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );\r\n\t\t\tvar localThresholdSq = localThreshold * localThreshold;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar attributes = geometry.attributes;\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = indices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar a = indices[ i ];\r\n\r\n\t\t\t\t\t\t_position$1.fromArray( positions, a * 3 );\r\n\r\n\t\t\t\t\t\ttestPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positions.length / 3; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t_position$1.fromArray( positions, i * 3 );\r\n\r\n\t\t\t\t\t\ttestPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\r\n\t\t\t\tfor ( var i = 0, l = vertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\ttestPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar m, ml, name;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\t\t\t\tvar keys = Object.keys( morphAttributes );\r\n\r\n\t\t\t\tif ( keys.length > 0 ) {\r\n\r\n\t\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\r\n\r\n\t\t\t\t\tif ( morphAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.morphTargetInfluences = [];\r\n\t\t\t\t\t\tthis.morphTargetDictionary = {};\r\n\r\n\t\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\r\n\r\n\t\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\r\n\r\n\t\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\r\n\t\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar morphTargets = geometry.morphTargets;\r\n\r\n\t\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {\r\n\r\n\t\tvar rayPointDistanceSq = _ray$2.distanceSqToPoint( point );\r\n\r\n\t\tif ( rayPointDistanceSq < localThresholdSq ) {\r\n\r\n\t\t\tvar intersectPoint = new Vector3();\r\n\r\n\t\t\t_ray$2.closestPointToPoint( point, intersectPoint );\r\n\t\t\tintersectPoint.applyMatrix4( matrixWorld );\r\n\r\n\t\t\tvar distance = raycaster.ray.origin.distanceTo( intersectPoint );\r\n\r\n\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return; }\r\n\r\n\t\t\tintersects.push( {\r\n\r\n\t\t\t\tdistance: distance,\r\n\t\t\t\tdistanceToRay: Math.sqrt( rayPointDistanceSq ),\r\n\t\t\t\tpoint: intersectPoint,\r\n\t\t\t\tindex: index,\r\n\t\t\t\tface: null,\r\n\t\t\t\tobject: object\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {\r\n\r\n\t\tTexture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.format = format !== undefined ? format : RGBFormat;\r\n\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : LinearFilter;\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\r\n\t}\r\n\r\n\tVideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {\r\n\r\n\t\tconstructor: VideoTexture,\r\n\r\n\t\tisVideoTexture: true,\r\n\r\n\t\tupdate: function () {\r\n\r\n\t\t\tvar video = this.image;\r\n\r\n\t\t\tif ( video.readyState >= video.HAVE_CURRENT_DATA ) {\r\n\r\n\t\t\t\tthis.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.image = { width: width, height: height };\r\n\t\tthis.mipmaps = mipmaps;\r\n\r\n\t\t// no flipping for cube textures\r\n\t\t// (also flipping doesn't work for compressed textures )\r\n\r\n\t\tthis.flipY = false;\r\n\r\n\t\t// can't generate mipmaps for compressed textures\r\n\t\t// mips must be embedded in DDS files\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\r\n\t}\r\n\r\n\tCompressedTexture.prototype = Object.create( Texture.prototype );\r\n\tCompressedTexture.prototype.constructor = CompressedTexture;\r\n\r\n\tCompressedTexture.prototype.isCompressedTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {\r\n\r\n\t\tTexture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tCanvasTexture.prototype = Object.create( Texture.prototype );\r\n\tCanvasTexture.prototype.constructor = CanvasTexture;\r\n\tCanvasTexture.prototype.isCanvasTexture = true;\n\n\t/**\r\n\t * @author Matt DesLauriers / @mattdesl\r\n\t * @author atix / arthursilber.de\r\n\t */\r\n\r\n\tfunction DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {\r\n\r\n\t\tformat = format !== undefined ? format : DepthFormat;\r\n\r\n\t\tif ( format !== DepthFormat && format !== DepthStencilFormat ) {\r\n\r\n\t\t\tthrow new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( type === undefined && format === DepthFormat ) { type = UnsignedShortType; }\r\n\t\tif ( type === undefined && format === DepthStencilFormat ) { type = UnsignedInt248Type; }\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.image = { width: width, height: height };\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\r\n\r\n\t\tthis.flipY = false;\r\n\t\tthis.generateMipmaps\t= false;\r\n\r\n\t}\r\n\r\n\tDepthTexture.prototype = Object.create( Texture.prototype );\r\n\tDepthTexture.prototype.constructor = DepthTexture;\r\n\tDepthTexture.prototype.isDepthTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WireframeGeometry( geometry ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'WireframeGeometry';\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, j, l, o, ol;\r\n\t\tvar edge = [ 0, 0 ], edges = {}, e, edge1, edge2;\r\n\t\tvar key, keys = [ 'a', 'b', 'c' ];\r\n\t\tvar vertex;\r\n\r\n\t\t// different logic for Geometry and BufferGeometry\r\n\r\n\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\t// create a data structure that contains all edges without duplicates\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\r\n\t\t\tfor ( i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\tedge1 = face[ keys[ j ] ];\r\n\t\t\t\t\tedge2 = face[ keys[ ( j + 1 ) % 3 ] ];\r\n\t\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates\r\n\t\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate vertices\r\n\r\n\t\t\tfor ( key in edges ) {\r\n\r\n\t\t\t\te = edges[ key ];\r\n\r\n\t\t\t\tvertex = geometry.vertices[ e.index1 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\tvertex = geometry.vertices[ e.index2 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( geometry && geometry.isBufferGeometry ) {\r\n\r\n\t\t\tvar position, indices, groups;\r\n\t\t\tvar group, start, count;\r\n\t\t\tvar index1, index2;\r\n\r\n\t\t\tvertex = new Vector3();\r\n\r\n\t\t\tif ( geometry.index !== null ) {\r\n\r\n\t\t\t\t// indexed BufferGeometry\r\n\r\n\t\t\t\tposition = geometry.attributes.position;\r\n\t\t\t\tindices = geometry.index;\r\n\t\t\t\tgroups = geometry.groups;\r\n\r\n\t\t\t\tif ( groups.length === 0 ) {\r\n\r\n\t\t\t\t\tgroups = [ { start: 0, count: indices.count, materialIndex: 0 } ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// create a data structure that contains all eges without duplicates\r\n\r\n\t\t\t\tfor ( o = 0, ol = groups.length; o < ol; ++ o ) {\r\n\r\n\t\t\t\t\tgroup = groups[ o ];\r\n\r\n\t\t\t\t\tstart = group.start;\r\n\t\t\t\t\tcount = group.count;\r\n\r\n\t\t\t\t\tfor ( i = start, l = ( start + count ); i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tedge1 = indices.getX( i + j );\r\n\t\t\t\t\t\t\tedge2 = indices.getX( i + ( j + 1 ) % 3 );\r\n\t\t\t\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates\r\n\t\t\t\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// generate vertices\r\n\r\n\t\t\t\tfor ( key in edges ) {\r\n\r\n\t\t\t\t\te = edges[ key ];\r\n\r\n\t\t\t\t\tvertex.fromBufferAttribute( position, e.index1 );\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\tvertex.fromBufferAttribute( position, e.index2 );\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// non-indexed BufferGeometry\r\n\r\n\t\t\t\tposition = geometry.attributes.position;\r\n\r\n\t\t\t\tfor ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {\r\n\r\n\t\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\t\t// three edges per triangle, an edge is represented as (index1, index2)\r\n\t\t\t\t\t\t// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)\r\n\r\n\t\t\t\t\t\tindex1 = 3 * i + j;\r\n\t\t\t\t\t\tvertex.fromBufferAttribute( position, index1 );\r\n\t\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t\tindex2 = 3 * i + ( ( j + 1 ) % 3 );\r\n\t\t\t\t\t\tvertex.fromBufferAttribute( position, index2 );\r\n\t\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\r\n\t}\r\n\r\n\tWireframeGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tWireframeGeometry.prototype.constructor = WireframeGeometry;\n\n\t/**\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * Parametric Surfaces Geometry\r\n\t * based on the brilliant article by @prideout http://prideout.net/blog/?p=44\r\n\t */\r\n\r\n\t// ParametricGeometry\r\n\r\n\tfunction ParametricGeometry( func, slices, stacks ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ParametricGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tfunc: func,\r\n\t\t\tslices: slices,\r\n\t\t\tstacks: stacks\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tParametricGeometry.prototype = Object.create( Geometry.prototype );\r\n\tParametricGeometry.prototype.constructor = ParametricGeometry;\r\n\r\n\t// ParametricBufferGeometry\r\n\r\n\tfunction ParametricBufferGeometry( func, slices, stacks ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ParametricBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tfunc: func,\r\n\t\t\tslices: slices,\r\n\t\t\tstacks: stacks\r\n\t\t};\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\tvar EPS = 0.00001;\r\n\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar p0 = new Vector3(), p1 = new Vector3();\r\n\t\tvar pu = new Vector3(), pv = new Vector3();\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tif ( func.length < 3 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );\r\n\r\n\t\t}\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tvar sliceCount = slices + 1;\r\n\r\n\t\tfor ( i = 0; i <= stacks; i ++ ) {\r\n\r\n\t\t\tvar v = i / stacks;\r\n\r\n\t\t\tfor ( j = 0; j <= slices; j ++ ) {\r\n\r\n\t\t\t\tvar u = j / slices;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tfunc( u, v, p0 );\r\n\t\t\t\tvertices.push( p0.x, p0.y, p0.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\t// approximate tangent vectors via finite differences\r\n\r\n\t\t\t\tif ( u - EPS >= 0 ) {\r\n\r\n\t\t\t\t\tfunc( u - EPS, v, p1 );\r\n\t\t\t\t\tpu.subVectors( p0, p1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfunc( u + EPS, v, p1 );\r\n\t\t\t\t\tpu.subVectors( p1, p0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( v - EPS >= 0 ) {\r\n\r\n\t\t\t\t\tfunc( u, v - EPS, p1 );\r\n\t\t\t\t\tpv.subVectors( p0, p1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfunc( u, v + EPS, p1 );\r\n\t\t\t\t\tpv.subVectors( p1, p0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// cross product of tangent vectors returns surface normal\r\n\r\n\t\t\t\tnormal.crossVectors( pu, pv ).normalize();\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( u, v );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( i = 0; i < stacks; i ++ ) {\r\n\r\n\t\t\tfor ( j = 0; j < slices; j ++ ) {\r\n\r\n\t\t\t\tvar a = i * sliceCount + j;\r\n\t\t\t\tvar b = i * sliceCount + j + 1;\r\n\t\t\t\tvar c = ( i + 1 ) * sliceCount + j + 1;\r\n\t\t\t\tvar d = ( i + 1 ) * sliceCount + j;\r\n\r\n\t\t\t\t// faces one and two\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;\n\n\t/**\r\n\t * @author clockworkgeek / https://github.com/clockworkgeek\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// PolyhedronGeometry\r\n\r\n\tfunction PolyhedronGeometry( vertices, indices, radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'PolyhedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tvertices: vertices,\r\n\t\t\tindices: indices,\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tPolyhedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tPolyhedronGeometry.prototype.constructor = PolyhedronGeometry;\r\n\r\n\t// PolyhedronBufferGeometry\r\n\r\n\tfunction PolyhedronBufferGeometry( vertices, indices, radius, detail ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'PolyhedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tvertices: vertices,\r\n\t\t\tindices: indices,\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\tdetail = detail || 0;\r\n\r\n\t\t// default buffer data\r\n\r\n\t\tvar vertexBuffer = [];\r\n\t\tvar uvBuffer = [];\r\n\r\n\t\t// the subdivision creates the vertex buffer data\r\n\r\n\t\tsubdivide( detail );\r\n\r\n\t\t// all vertices should lie on a conceptual sphere with a given radius\r\n\r\n\t\tapplyRadius( radius );\r\n\r\n\t\t// finally, create the uv data\r\n\r\n\t\tgenerateUVs();\r\n\r\n\t\t// build non-indexed geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );\r\n\r\n\t\tif ( detail === 0 ) {\r\n\r\n\t\t\tthis.computeVertexNormals(); // flat normals\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.normalizeNormals(); // smooth normals\r\n\r\n\t\t}\r\n\r\n\t\t// helper functions\r\n\r\n\t\tfunction subdivide( detail ) {\r\n\r\n\t\t\tvar a = new Vector3();\r\n\t\t\tvar b = new Vector3();\r\n\t\t\tvar c = new Vector3();\r\n\r\n\t\t\t// iterate over all faces and apply a subdivison with the given detail value\r\n\r\n\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\r\n\r\n\t\t\t\t// get the vertices of the face\r\n\r\n\t\t\t\tgetVertexByIndex( indices[ i + 0 ], a );\r\n\t\t\t\tgetVertexByIndex( indices[ i + 1 ], b );\r\n\t\t\t\tgetVertexByIndex( indices[ i + 2 ], c );\r\n\r\n\t\t\t\t// perform subdivision\r\n\r\n\t\t\t\tsubdivideFace( a, b, c, detail );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction subdivideFace( a, b, c, detail ) {\r\n\r\n\t\t\tvar cols = Math.pow( 2, detail );\r\n\r\n\t\t\t// we use this multidimensional array as a data structure for creating the subdivision\r\n\r\n\t\t\tvar v = [];\r\n\r\n\t\t\tvar i, j;\r\n\r\n\t\t\t// construct all of the vertices for this subdivision\r\n\r\n\t\t\tfor ( i = 0; i <= cols; i ++ ) {\r\n\r\n\t\t\t\tv[ i ] = [];\r\n\r\n\t\t\t\tvar aj = a.clone().lerp( c, i / cols );\r\n\t\t\t\tvar bj = b.clone().lerp( c, i / cols );\r\n\r\n\t\t\t\tvar rows = cols - i;\r\n\r\n\t\t\t\tfor ( j = 0; j <= rows; j ++ ) {\r\n\r\n\t\t\t\t\tif ( j === 0 && i === cols ) {\r\n\r\n\t\t\t\t\t\tv[ i ][ j ] = aj;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tv[ i ][ j ] = aj.clone().lerp( bj, j / rows );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// construct all of the faces\r\n\r\n\t\t\tfor ( i = 0; i < cols; i ++ ) {\r\n\r\n\t\t\t\tfor ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {\r\n\r\n\t\t\t\t\tvar k = Math.floor( j / 2 );\r\n\r\n\t\t\t\t\tif ( j % 2 === 0 ) {\r\n\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k ] );\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction applyRadius( radius ) {\r\n\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\t// iterate over the entire buffer and apply the radius to each vertex\r\n\r\n\t\t\tfor ( var i = 0; i < vertexBuffer.length; i += 3 ) {\r\n\r\n\t\t\t\tvertex.x = vertexBuffer[ i + 0 ];\r\n\t\t\t\tvertex.y = vertexBuffer[ i + 1 ];\r\n\t\t\t\tvertex.z = vertexBuffer[ i + 2 ];\r\n\r\n\t\t\t\tvertex.normalize().multiplyScalar( radius );\r\n\r\n\t\t\t\tvertexBuffer[ i + 0 ] = vertex.x;\r\n\t\t\t\tvertexBuffer[ i + 1 ] = vertex.y;\r\n\t\t\t\tvertexBuffer[ i + 2 ] = vertex.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateUVs() {\r\n\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tfor ( var i = 0; i < vertexBuffer.length; i += 3 ) {\r\n\r\n\t\t\t\tvertex.x = vertexBuffer[ i + 0 ];\r\n\t\t\t\tvertex.y = vertexBuffer[ i + 1 ];\r\n\t\t\t\tvertex.z = vertexBuffer[ i + 2 ];\r\n\r\n\t\t\t\tvar u = azimuth( vertex ) / 2 / Math.PI + 0.5;\r\n\t\t\t\tvar v = inclination( vertex ) / Math.PI + 0.5;\r\n\t\t\t\tuvBuffer.push( u, 1 - v );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcorrectUVs();\r\n\r\n\t\t\tcorrectSeam();\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctSeam() {\r\n\r\n\t\t\t// handle case when face straddles the seam, see #3269\r\n\r\n\t\t\tfor ( var i = 0; i < uvBuffer.length; i += 6 ) {\r\n\r\n\t\t\t\t// uv data of a single face\r\n\r\n\t\t\t\tvar x0 = uvBuffer[ i + 0 ];\r\n\t\t\t\tvar x1 = uvBuffer[ i + 2 ];\r\n\t\t\t\tvar x2 = uvBuffer[ i + 4 ];\r\n\r\n\t\t\t\tvar max = Math.max( x0, x1, x2 );\r\n\t\t\t\tvar min = Math.min( x0, x1, x2 );\r\n\r\n\t\t\t\t// 0.9 is somewhat arbitrary\r\n\r\n\t\t\t\tif ( max > 0.9 && min < 0.1 ) {\r\n\r\n\t\t\t\t\tif ( x0 < 0.2 ) { uvBuffer[ i + 0 ] += 1; }\r\n\t\t\t\t\tif ( x1 < 0.2 ) { uvBuffer[ i + 2 ] += 1; }\r\n\t\t\t\t\tif ( x2 < 0.2 ) { uvBuffer[ i + 4 ] += 1; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushVertex( vertex ) {\r\n\r\n\t\t\tvertexBuffer.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getVertexByIndex( index, vertex ) {\r\n\r\n\t\t\tvar stride = index * 3;\r\n\r\n\t\t\tvertex.x = vertices[ stride + 0 ];\r\n\t\t\tvertex.y = vertices[ stride + 1 ];\r\n\t\t\tvertex.z = vertices[ stride + 2 ];\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctUVs() {\r\n\r\n\t\t\tvar a = new Vector3();\r\n\t\t\tvar b = new Vector3();\r\n\t\t\tvar c = new Vector3();\r\n\r\n\t\t\tvar centroid = new Vector3();\r\n\r\n\t\t\tvar uvA = new Vector2();\r\n\t\t\tvar uvB = new Vector2();\r\n\t\t\tvar uvC = new Vector2();\r\n\r\n\t\t\tfor ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {\r\n\r\n\t\t\t\ta.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );\r\n\t\t\t\tb.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );\r\n\t\t\t\tc.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );\r\n\r\n\t\t\t\tuvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );\r\n\t\t\t\tuvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );\r\n\t\t\t\tuvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );\r\n\r\n\t\t\t\tcentroid.copy( a ).add( b ).add( c ).divideScalar( 3 );\r\n\r\n\t\t\t\tvar azi = azimuth( centroid );\r\n\r\n\t\t\t\tcorrectUV( uvA, j + 0, a, azi );\r\n\t\t\t\tcorrectUV( uvB, j + 2, b, azi );\r\n\t\t\t\tcorrectUV( uvC, j + 4, c, azi );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctUV( uv, stride, vector, azimuth ) {\r\n\r\n\t\t\tif ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {\r\n\r\n\t\t\t\tuvBuffer[ stride ] = uv.x - 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {\r\n\r\n\t\t\t\tuvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Angle around the Y axis, counter-clockwise when looking from above.\r\n\r\n\t\tfunction azimuth( vector ) {\r\n\r\n\t\t\treturn Math.atan2( vector.z, - vector.x );\r\n\r\n\t\t}\r\n\r\n\r\n\t\t// Angle above the XZ plane.\r\n\r\n\t\tfunction inclination( vector ) {\r\n\r\n\t\t\treturn Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tPolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tPolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// TetrahedronGeometry\r\n\r\n\tfunction TetrahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TetrahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTetrahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTetrahedronGeometry.prototype.constructor = TetrahedronGeometry;\r\n\r\n\t// TetrahedronBufferGeometry\r\n\r\n\tfunction TetrahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar vertices = [\r\n\t\t\t1, 1, 1, \t- 1, - 1, 1, \t- 1, 1, - 1, \t1, - 1, - 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t2, 1, 0, \t0, 3, 2,\t1, 3, 0,\t2, 3, 1\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'TetrahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tTetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tTetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// OctahedronGeometry\r\n\r\n\tfunction OctahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'OctahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tOctahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tOctahedronGeometry.prototype.constructor = OctahedronGeometry;\r\n\r\n\t// OctahedronBufferGeometry\r\n\r\n\tfunction OctahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar vertices = [\r\n\t\t\t1, 0, 0, \t- 1, 0, 0,\t0, 1, 0,\r\n\t\t\t0, - 1, 0, \t0, 0, 1,\t0, 0, - 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t0, 2, 4,\t0, 4, 3,\t0, 3, 5,\r\n\t\t\t0, 5, 2,\t1, 2, 5,\t1, 5, 3,\r\n\t\t\t1, 3, 4,\t1, 4, 2\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'OctahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tOctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tOctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// IcosahedronGeometry\r\n\r\n\tfunction IcosahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'IcosahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tIcosahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tIcosahedronGeometry.prototype.constructor = IcosahedronGeometry;\r\n\r\n\t// IcosahedronBufferGeometry\r\n\r\n\tfunction IcosahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar t = ( 1 + Math.sqrt( 5 ) ) / 2;\r\n\r\n\t\tvar vertices = [\r\n\t\t\t- 1, t, 0, \t1, t, 0, \t- 1, - t, 0, \t1, - t, 0,\r\n\t\t\t 0, - 1, t, \t0, 1, t,\t0, - 1, - t, \t0, 1, - t,\r\n\t\t\t t, 0, - 1, \tt, 0, 1, \t- t, 0, - 1, \t- t, 0, 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t 0, 11, 5, \t0, 5, 1, \t0, 1, 7, \t0, 7, 10, \t0, 10, 11,\r\n\t\t\t 1, 5, 9, \t5, 11, 4,\t11, 10, 2,\t10, 7, 6,\t7, 1, 8,\r\n\t\t\t 3, 9, 4, \t3, 4, 2,\t3, 2, 6,\t3, 6, 8,\t3, 8, 9,\r\n\t\t\t 4, 9, 5, \t2, 4, 11,\t6, 2, 10,\t8, 6, 7,\t9, 8, 1\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'IcosahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tIcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tIcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;\n\n\t/**\r\n\t * @author Abe Pazos / https://hamoid.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// DodecahedronGeometry\r\n\r\n\tfunction DodecahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'DodecahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tDodecahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tDodecahedronGeometry.prototype.constructor = DodecahedronGeometry;\r\n\r\n\t// DodecahedronBufferGeometry\r\n\r\n\tfunction DodecahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar t = ( 1 + Math.sqrt( 5 ) ) / 2;\r\n\t\tvar r = 1 / t;\r\n\r\n\t\tvar vertices = [\r\n\r\n\t\t\t// (±1, ±1, ±1)\r\n\t\t\t- 1, - 1, - 1,\t- 1, - 1, 1,\r\n\t\t\t- 1, 1, - 1, - 1, 1, 1,\r\n\t\t\t1, - 1, - 1, 1, - 1, 1,\r\n\t\t\t1, 1, - 1, 1, 1, 1,\r\n\r\n\t\t\t// (0, ±1/φ, ±φ)\r\n\t\t\t 0, - r, - t, 0, - r, t,\r\n\t\t\t 0, r, - t, 0, r, t,\r\n\r\n\t\t\t// (±1/φ, ±φ, 0)\r\n\t\t\t- r, - t, 0, - r, t, 0,\r\n\t\t\t r, - t, 0, r, t, 0,\r\n\r\n\t\t\t// (±φ, 0, ±1/φ)\r\n\t\t\t- t, 0, - r, t, 0, - r,\r\n\t\t\t- t, 0, r, t, 0, r\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t3, 11, 7, \t3, 7, 15, \t3, 15, 13,\r\n\t\t\t7, 19, 17, \t7, 17, 6, \t7, 6, 15,\r\n\t\t\t17, 4, 8, \t17, 8, 10, \t17, 10, 6,\r\n\t\t\t8, 0, 16, \t8, 16, 2, \t8, 2, 10,\r\n\t\t\t0, 12, 1, \t0, 1, 18, \t0, 18, 16,\r\n\t\t\t6, 10, 2, \t6, 2, 13, \t6, 13, 15,\r\n\t\t\t2, 16, 18, \t2, 18, 3, \t2, 3, 13,\r\n\t\t\t18, 1, 9, \t18, 9, 11, \t18, 11, 3,\r\n\t\t\t4, 14, 12, \t4, 12, 0, \t4, 0, 8,\r\n\t\t\t11, 9, 5, \t11, 5, 19, \t11, 19, 7,\r\n\t\t\t19, 5, 14, \t19, 14, 4, \t19, 4, 17,\r\n\t\t\t1, 12, 14, \t1, 14, 5, \t1, 5, 9\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'DodecahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tDodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tDodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;\n\n\t/**\r\n\t * @author oosmoxiecode / https://github.com/oosmoxiecode\r\n\t * @author WestLangley / https://github.com/WestLangley\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author miningold / https://github.com/miningold\r\n\t * @author jonobr1 / https://github.com/jonobr1\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t */\r\n\r\n\t// TubeGeometry\r\n\r\n\tfunction TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TubeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpath: path,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradius: radius,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tclosed: closed\r\n\t\t};\r\n\r\n\t\tif ( taper !== undefined ) { console.warn( 'THREE.TubeGeometry: taper has been removed.' ); }\r\n\r\n\t\tvar bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );\r\n\r\n\t\t// expose internals\r\n\r\n\t\tthis.tangents = bufferGeometry.tangents;\r\n\t\tthis.normals = bufferGeometry.normals;\r\n\t\tthis.binormals = bufferGeometry.binormals;\r\n\r\n\t\t// create geometry\r\n\r\n\t\tthis.fromBufferGeometry( bufferGeometry );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTubeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTubeGeometry.prototype.constructor = TubeGeometry;\r\n\r\n\t// TubeBufferGeometry\r\n\r\n\tfunction TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TubeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpath: path,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradius: radius,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tclosed: closed\r\n\t\t};\r\n\r\n\t\ttubularSegments = tubularSegments || 64;\r\n\t\tradius = radius || 1;\r\n\t\tradialSegments = radialSegments || 8;\r\n\t\tclosed = closed || false;\r\n\r\n\t\tvar frames = path.computeFrenetFrames( tubularSegments, closed );\r\n\r\n\t\t// expose internals\r\n\r\n\t\tthis.tangents = frames.tangents;\r\n\t\tthis.normals = frames.normals;\r\n\t\tthis.binormals = frames.binormals;\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar P = new Vector3();\r\n\r\n\t\tvar i, j;\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\t\tvar indices = [];\r\n\r\n\t\t// create buffer data\r\n\r\n\t\tgenerateBufferData();\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// functions\r\n\r\n\t\tfunction generateBufferData() {\r\n\r\n\t\t\tfor ( i = 0; i < tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tgenerateSegment( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// if the geometry is not closed, generate the last row of vertices and normals\r\n\t\t\t// at the regular position on the given path\r\n\t\t\t//\r\n\t\t\t// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)\r\n\r\n\t\t\tgenerateSegment( ( closed === false ) ? tubularSegments : 0 );\r\n\r\n\t\t\t// uvs are generated in a separate function.\r\n\t\t\t// this makes it easy compute correct values for closed geometries\r\n\r\n\t\t\tgenerateUVs();\r\n\r\n\t\t\t// finally create faces\r\n\r\n\t\t\tgenerateIndices();\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateSegment( i ) {\r\n\r\n\t\t\t// we use getPointAt to sample evenly distributed points from the given path\r\n\r\n\t\t\tP = path.getPointAt( i / tubularSegments, P );\r\n\r\n\t\t\t// retrieve corresponding normal and binormal\r\n\r\n\t\t\tvar N = frames.normals[ i ];\r\n\t\t\tvar B = frames.binormals[ i ];\r\n\r\n\t\t\t// generate normals and vertices for the current segment\r\n\r\n\t\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\r\n\t\t\t\tvar sin = Math.sin( v );\r\n\t\t\t\tvar cos = - Math.cos( v );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormal.x = ( cos * N.x + sin * B.x );\r\n\t\t\t\tnormal.y = ( cos * N.y + sin * B.y );\r\n\t\t\t\tnormal.z = ( cos * N.z + sin * B.z );\r\n\t\t\t\tnormal.normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = P.x + radius * normal.x;\r\n\t\t\t\tvertex.y = P.y + radius * normal.y;\r\n\t\t\t\tvertex.z = P.z + radius * normal.z;\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateIndices() {\r\n\r\n\t\t\tfor ( j = 1; j <= tubularSegments; j ++ ) {\r\n\r\n\t\t\t\tfor ( i = 1; i <= radialSegments; i ++ ) {\r\n\r\n\t\t\t\t\tvar a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );\r\n\t\t\t\t\tvar b = ( radialSegments + 1 ) * j + ( i - 1 );\r\n\t\t\t\t\tvar c = ( radialSegments + 1 ) * j + i;\r\n\t\t\t\t\tvar d = ( radialSegments + 1 ) * ( j - 1 ) + i;\r\n\r\n\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateUVs() {\r\n\r\n\t\t\tfor ( i = 0; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\t\t\tuv.x = i / tubularSegments;\r\n\t\t\t\t\tuv.y = j / radialSegments;\r\n\r\n\t\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tTubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTubeBufferGeometry.prototype.constructor = TubeBufferGeometry;\r\n\r\n\tTubeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tdata.path = this.parameters.path.toJSON();\r\n\r\n\t\treturn data;\r\n\r\n\t};\n\n\t/**\r\n\t * @author oosmoxiecode\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * based on http://www.blackpawn.com/texts/pqtorus/\r\n\t */\r\n\r\n\t// TorusKnotGeometry\r\n\r\n\tfunction TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusKnotGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tp: p,\r\n\t\t\tq: q\r\n\t\t};\r\n\r\n\t\tif ( heightScale !== undefined ) { console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); }\r\n\r\n\t\tthis.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTorusKnotGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTorusKnotGeometry.prototype.constructor = TorusKnotGeometry;\r\n\r\n\t// TorusKnotBufferGeometry\r\n\r\n\tfunction TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusKnotBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tp: p,\r\n\t\t\tq: q\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\ttube = tube || 0.4;\r\n\t\ttubularSegments = Math.floor( tubularSegments ) || 64;\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\tp = p || 2;\r\n\t\tq = q || 3;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar P1 = new Vector3();\r\n\t\tvar P2 = new Vector3();\r\n\r\n\t\tvar B = new Vector3();\r\n\t\tvar T = new Vector3();\r\n\t\tvar N = new Vector3();\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( i = 0; i <= tubularSegments; ++ i ) {\r\n\r\n\t\t\t// the radian \"u\" is used to calculate the position on the torus curve of the current tubular segement\r\n\r\n\t\t\tvar u = i / tubularSegments * p * Math.PI * 2;\r\n\r\n\t\t\t// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.\r\n\t\t\t// these points are used to create a special \"coordinate space\", which is necessary to calculate the correct vertex positions\r\n\r\n\t\t\tcalculatePositionOnCurve( u, p, q, radius, P1 );\r\n\t\t\tcalculatePositionOnCurve( u + 0.01, p, q, radius, P2 );\r\n\r\n\t\t\t// calculate orthonormal basis\r\n\r\n\t\t\tT.subVectors( P2, P1 );\r\n\t\t\tN.addVectors( P2, P1 );\r\n\t\t\tB.crossVectors( T, N );\r\n\t\t\tN.crossVectors( B, T );\r\n\r\n\t\t\t// normalize B, N. T can be ignored, we don't use it\r\n\r\n\t\t\tB.normalize();\r\n\t\t\tN.normalize();\r\n\r\n\t\t\tfor ( j = 0; j <= radialSegments; ++ j ) {\r\n\r\n\t\t\t\t// now calculate the vertices. they are nothing more than an extrusion of the torus curve.\r\n\t\t\t\t// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.\r\n\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\t\t\t\tvar cx = - tube * Math.cos( v );\r\n\t\t\t\tvar cy = tube * Math.sin( v );\r\n\r\n\t\t\t\t// now calculate the final vertex position.\r\n\t\t\t\t// first we orient the extrusion with our basis vectos, then we add it to the current position on the curve\r\n\r\n\t\t\t\tvertex.x = P1.x + ( cx * N.x + cy * B.x );\r\n\t\t\t\tvertex.y = P1.y + ( cx * N.y + cy * B.y );\r\n\t\t\t\tvertex.z = P1.z + ( cx * N.z + cy * B.z );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)\r\n\r\n\t\t\t\tnormal.subVectors( vertex, P1 ).normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( i / tubularSegments );\r\n\t\t\t\tuvs.push( j / radialSegments );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( j = 1; j <= tubularSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 1; i <= radialSegments; i ++ ) {\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\tvar a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );\r\n\t\t\t\tvar b = ( radialSegments + 1 ) * j + ( i - 1 );\r\n\t\t\t\tvar c = ( radialSegments + 1 ) * j + i;\r\n\t\t\t\tvar d = ( radialSegments + 1 ) * ( j - 1 ) + i;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// this function calculates the current position on the torus curve\r\n\r\n\t\tfunction calculatePositionOnCurve( u, p, q, radius, position ) {\r\n\r\n\t\t\tvar cu = Math.cos( u );\r\n\t\t\tvar su = Math.sin( u );\r\n\t\t\tvar quOverP = q / p * u;\r\n\t\t\tvar cs = Math.cos( quOverP );\r\n\r\n\t\t\tposition.x = radius * ( 2 + cs ) * 0.5 * cu;\r\n\t\t\tposition.y = radius * ( 2 + cs ) * su * 0.5;\r\n\t\t\tposition.z = radius * Math.sin( quOverP ) * 0.5;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tTorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;\n\n\t/**\r\n\t * @author oosmoxiecode\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// TorusGeometry\r\n\r\n\tfunction TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tarc: arc\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTorusGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTorusGeometry.prototype.constructor = TorusGeometry;\r\n\r\n\t// TorusBufferGeometry\r\n\r\n\tfunction TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tarc: arc\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\ttube = tube || 0.4;\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\ttubularSegments = Math.floor( tubularSegments ) || 6;\r\n\t\tarc = arc || Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar center = new Vector3();\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar j, i;\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 0; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tvar u = i / tubularSegments * arc;\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );\r\n\t\t\t\tvertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );\r\n\t\t\t\tvertex.z = tube * Math.sin( v );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tcenter.x = radius * Math.cos( u );\r\n\t\t\t\tcenter.y = radius * Math.sin( u );\r\n\t\t\t\tnormal.subVectors( vertex, center ).normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( i / tubularSegments );\r\n\t\t\t\tuvs.push( j / radialSegments );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( j = 1; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 1; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\tvar a = ( tubularSegments + 1 ) * j + i - 1;\r\n\t\t\t\tvar b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;\r\n\t\t\t\tvar c = ( tubularSegments + 1 ) * ( j - 1 ) + i;\r\n\t\t\t\tvar d = ( tubularSegments + 1 ) * j + i;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tTorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTorusBufferGeometry.prototype.constructor = TorusBufferGeometry;\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * Port from https://github.com/mapbox/earcut (v2.1.5)\r\n\t */\r\n\r\n\tvar Earcut = {\r\n\r\n\t\ttriangulate: function ( data, holeIndices, dim ) {\r\n\r\n\t\t\tdim = dim || 2;\r\n\r\n\t\t\tvar hasHoles = holeIndices && holeIndices.length,\r\n\t\t\t\touterLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,\r\n\t\t\t\touterNode = linkedList( data, 0, outerLen, dim, true ),\r\n\t\t\t\ttriangles = [];\r\n\r\n\t\t\tif ( ! outerNode || outerNode.next === outerNode.prev ) { return triangles; }\r\n\r\n\t\t\tvar minX, minY, maxX, maxY, x, y, invSize;\r\n\r\n\t\t\tif ( hasHoles ) { outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); }\r\n\r\n\t\t\t// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\r\n\t\t\tif ( data.length > 80 * dim ) {\r\n\r\n\t\t\t\tminX = maxX = data[ 0 ];\r\n\t\t\t\tminY = maxY = data[ 1 ];\r\n\r\n\t\t\t\tfor ( var i = dim; i < outerLen; i += dim ) {\r\n\r\n\t\t\t\t\tx = data[ i ];\r\n\t\t\t\t\ty = data[ i + 1 ];\r\n\t\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// minX, minY and invSize are later used to transform coords into integers for z-order calculation\r\n\t\t\t\tinvSize = Math.max( maxX - minX, maxY - minY );\r\n\t\t\t\tinvSize = invSize !== 0 ? 1 / invSize : 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tearcutLinked( outerNode, triangles, dim, minX, minY, invSize );\r\n\r\n\t\t\treturn triangles;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t// create a circular doubly linked list from polygon points in the specified winding order\r\n\tfunction linkedList( data, start, end, dim, clockwise ) {\r\n\r\n\t\tvar i, last;\r\n\r\n\t\tif ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {\r\n\r\n\t\t\tfor ( i = start; i < end; i += dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); }\r\n\r\n\t\t} else {\r\n\r\n\t\t\tfor ( i = end - dim; i >= start; i -= dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); }\r\n\r\n\t\t}\r\n\r\n\t\tif ( last && equals( last, last.next ) ) {\r\n\r\n\t\t\tremoveNode( last );\r\n\t\t\tlast = last.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn last;\r\n\r\n\t}\r\n\r\n\t// eliminate colinear or duplicate points\r\n\tfunction filterPoints( start, end ) {\r\n\r\n\t\tif ( ! start ) { return start; }\r\n\t\tif ( ! end ) { end = start; }\r\n\r\n\t\tvar p = start,\r\n\t\t\tagain;\r\n\t\tdo {\r\n\r\n\t\t\tagain = false;\r\n\r\n\t\t\tif ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {\r\n\r\n\t\t\t\tremoveNode( p );\r\n\t\t\t\tp = end = p.prev;\r\n\t\t\t\tif ( p === p.next ) { break; }\r\n\t\t\t\tagain = true;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp = p.next;\r\n\r\n\t\t\t}\r\n\r\n\t\t} while ( again || p !== end );\r\n\r\n\t\treturn end;\r\n\r\n\t}\r\n\r\n\t// main ear slicing loop which triangulates a polygon (given as a linked list)\r\n\tfunction earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {\r\n\r\n\t\tif ( ! ear ) { return; }\r\n\r\n\t\t// interlink polygon nodes in z-order\r\n\t\tif ( ! pass && invSize ) { indexCurve( ear, minX, minY, invSize ); }\r\n\r\n\t\tvar stop = ear,\r\n\t\t\tprev, next;\r\n\r\n\t\t// iterate through ears, slicing them one by one\r\n\t\twhile ( ear.prev !== ear.next ) {\r\n\r\n\t\t\tprev = ear.prev;\r\n\t\t\tnext = ear.next;\r\n\r\n\t\t\tif ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {\r\n\r\n\t\t\t\t// cut off the triangle\r\n\t\t\t\ttriangles.push( prev.i / dim );\r\n\t\t\t\ttriangles.push( ear.i / dim );\r\n\t\t\t\ttriangles.push( next.i / dim );\r\n\r\n\t\t\t\tremoveNode( ear );\r\n\r\n\t\t\t\t// skipping the next vertex leads to less sliver triangles\r\n\t\t\t\tear = next.next;\r\n\t\t\t\tstop = next.next;\r\n\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tear = next;\r\n\r\n\t\t\t// if we looped through the whole remaining polygon and can't find any more ears\r\n\t\t\tif ( ear === stop ) {\r\n\r\n\t\t\t\t// try filtering points and slicing again\r\n\t\t\t\tif ( ! pass ) {\r\n\r\n\t\t\t\t\tearcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );\r\n\r\n\t\t\t\t\t// if this didn't work, try curing all small self-intersections locally\r\n\r\n\t\t\t\t} else if ( pass === 1 ) {\r\n\r\n\t\t\t\t\tear = cureLocalIntersections( ear, triangles, dim );\r\n\t\t\t\t\tearcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );\r\n\r\n\t\t\t\t\t// as a last resort, try splitting the remaining polygon into two\r\n\r\n\t\t\t\t} else if ( pass === 2 ) {\r\n\r\n\t\t\t\t\tsplitEarcut( ear, triangles, dim, minX, minY, invSize );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// check whether a polygon node forms a valid ear with adjacent nodes\r\n\tfunction isEar( ear ) {\r\n\r\n\t\tvar a = ear.prev,\r\n\t\t\tb = ear,\r\n\t\t\tc = ear.next;\r\n\r\n\t\tif ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear\r\n\r\n\t\t// now make sure we don't have other points inside the potential ear\r\n\t\tvar p = ear.next.next;\r\n\r\n\t\twhile ( p !== ear.prev ) {\r\n\r\n\t\t\tif ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\tfunction isEarHashed( ear, minX, minY, invSize ) {\r\n\r\n\t\tvar a = ear.prev,\r\n\t\t\tb = ear,\r\n\t\t\tc = ear.next;\r\n\r\n\t\tif ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear\r\n\r\n\t\t// triangle bbox; min & max are calculated like this for speed\r\n\t\tvar minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),\r\n\t\t\tminTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),\r\n\t\t\tmaxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),\r\n\t\t\tmaxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );\r\n\r\n\t\t// z-order range for the current triangle bbox;\r\n\t\tvar minZ = zOrder( minTX, minTY, minX, minY, invSize ),\r\n\t\t\tmaxZ = zOrder( maxTX, maxTY, minX, minY, invSize );\r\n\r\n\t\tvar p = ear.prevZ,\r\n\t\t\tn = ear.nextZ;\r\n\r\n\t\t// look for points inside the triangle in both directions\r\n\t\twhile ( p && p.z >= minZ && n && n.z <= maxZ ) {\r\n\r\n\t\t\tif ( p !== ear.prev && p !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.prevZ;\r\n\r\n\t\t\tif ( n !== ear.prev && n !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&\r\n\t\t\t\tarea( n.prev, n, n.next ) >= 0 ) { return false; }\r\n\t\t\tn = n.nextZ;\r\n\r\n\t\t}\r\n\r\n\t\t// look for remaining points in decreasing z-order\r\n\t\twhile ( p && p.z >= minZ ) {\r\n\r\n\t\t\tif ( p !== ear.prev && p !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.prevZ;\r\n\r\n\t\t}\r\n\r\n\t\t// look for remaining points in increasing z-order\r\n\t\twhile ( n && n.z <= maxZ ) {\r\n\r\n\t\t\tif ( n !== ear.prev && n !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&\r\n\t\t\t\tarea( n.prev, n, n.next ) >= 0 ) { return false; }\r\n\t\t\tn = n.nextZ;\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\t// go through all polygon nodes and cure small local self-intersections\r\n\tfunction cureLocalIntersections( start, triangles, dim ) {\r\n\r\n\t\tvar p = start;\r\n\t\tdo {\r\n\r\n\t\t\tvar a = p.prev,\r\n\t\t\t\tb = p.next.next;\r\n\r\n\t\t\tif ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {\r\n\r\n\t\t\t\ttriangles.push( a.i / dim );\r\n\t\t\t\ttriangles.push( p.i / dim );\r\n\t\t\t\ttriangles.push( b.i / dim );\r\n\r\n\t\t\t\t// remove two nodes involved\r\n\t\t\t\tremoveNode( p );\r\n\t\t\t\tremoveNode( p.next );\r\n\r\n\t\t\t\tp = start = b;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\t// try splitting polygon into two and triangulate them independently\r\n\tfunction splitEarcut( start, triangles, dim, minX, minY, invSize ) {\r\n\r\n\t\t// look for a valid diagonal that divides the polygon into two\r\n\t\tvar a = start;\r\n\t\tdo {\r\n\r\n\t\t\tvar b = a.next.next;\r\n\t\t\twhile ( b !== a.prev ) {\r\n\r\n\t\t\t\tif ( a.i !== b.i && isValidDiagonal( a, b ) ) {\r\n\r\n\t\t\t\t\t// split the polygon in two by the diagonal\r\n\t\t\t\t\tvar c = splitPolygon( a, b );\r\n\r\n\t\t\t\t\t// filter colinear points around the cuts\r\n\t\t\t\t\ta = filterPoints( a, a.next );\r\n\t\t\t\t\tc = filterPoints( c, c.next );\r\n\r\n\t\t\t\t\t// run earcut on each half\r\n\t\t\t\t\tearcutLinked( a, triangles, dim, minX, minY, invSize );\r\n\t\t\t\t\tearcutLinked( c, triangles, dim, minX, minY, invSize );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tb = b.next;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ta = a.next;\r\n\r\n\t\t} while ( a !== start );\r\n\r\n\t}\r\n\r\n\t// link every hole into the outer loop, producing a single-ring polygon without holes\r\n\tfunction eliminateHoles( data, holeIndices, outerNode, dim ) {\r\n\r\n\t\tvar queue = [],\r\n\t\t\ti, len, start, end, list;\r\n\r\n\t\tfor ( i = 0, len = holeIndices.length; i < len; i ++ ) {\r\n\r\n\t\t\tstart = holeIndices[ i ] * dim;\r\n\t\t\tend = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;\r\n\t\t\tlist = linkedList( data, start, end, dim, false );\r\n\t\t\tif ( list === list.next ) { list.steiner = true; }\r\n\t\t\tqueue.push( getLeftmost( list ) );\r\n\r\n\t\t}\r\n\r\n\t\tqueue.sort( compareX );\r\n\r\n\t\t// process holes from left to right\r\n\t\tfor ( i = 0; i < queue.length; i ++ ) {\r\n\r\n\t\t\teliminateHole( queue[ i ], outerNode );\r\n\t\t\touterNode = filterPoints( outerNode, outerNode.next );\r\n\r\n\t\t}\r\n\r\n\t\treturn outerNode;\r\n\r\n\t}\r\n\r\n\tfunction compareX( a, b ) {\r\n\r\n\t\treturn a.x - b.x;\r\n\r\n\t}\r\n\r\n\t// find a bridge between vertices that connects hole with an outer ring and and link it\r\n\tfunction eliminateHole( hole, outerNode ) {\r\n\r\n\t\touterNode = findHoleBridge( hole, outerNode );\r\n\t\tif ( outerNode ) {\r\n\r\n\t\t\tvar b = splitPolygon( outerNode, hole );\r\n\t\t\tfilterPoints( b, b.next );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// David Eberly's algorithm for finding a bridge between hole and outer polygon\r\n\tfunction findHoleBridge( hole, outerNode ) {\r\n\r\n\t\tvar p = outerNode,\r\n\t\t\thx = hole.x,\r\n\t\t\thy = hole.y,\r\n\t\t\tqx = - Infinity,\r\n\t\t\tm;\r\n\r\n\t\t// find a segment intersected by a ray from the hole's leftmost point to the left;\r\n\t\t// segment's endpoint with lesser x will be potential connection point\r\n\t\tdo {\r\n\r\n\t\t\tif ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {\r\n\r\n\t\t\t\tvar x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );\r\n\t\t\t\tif ( x <= hx && x > qx ) {\r\n\r\n\t\t\t\t\tqx = x;\r\n\t\t\t\t\tif ( x === hx ) {\r\n\r\n\t\t\t\t\t\tif ( hy === p.y ) { return p; }\r\n\t\t\t\t\t\tif ( hy === p.next.y ) { return p.next; }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tm = p.x < p.next.x ? p : p.next;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== outerNode );\r\n\r\n\t\tif ( ! m ) { return null; }\r\n\r\n\t\tif ( hx === qx ) { return m.prev; } // hole touches outer segment; pick lower endpoint\r\n\r\n\t\t// look for points inside the triangle of hole point, segment intersection and endpoint;\r\n\t\t// if there are no points found, we have a valid connection;\r\n\t\t// otherwise choose the point of the minimum angle with the ray as connection point\r\n\r\n\t\tvar stop = m,\r\n\t\t\tmx = m.x,\r\n\t\t\tmy = m.y,\r\n\t\t\ttanMin = Infinity,\r\n\t\t\ttan;\r\n\r\n\t\tp = m.next;\r\n\r\n\t\twhile ( p !== stop ) {\r\n\r\n\t\t\tif ( hx >= p.x && p.x >= mx && hx !== p.x &&\r\n\t\t\t\t\tpointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {\r\n\r\n\t\t\t\ttan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential\r\n\r\n\t\t\t\tif ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {\r\n\r\n\t\t\t\t\tm = p;\r\n\t\t\t\t\ttanMin = tan;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn m;\r\n\r\n\t}\r\n\r\n\t// interlink polygon nodes in z-order\r\n\tfunction indexCurve( start, minX, minY, invSize ) {\r\n\r\n\t\tvar p = start;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.z === null ) { p.z = zOrder( p.x, p.y, minX, minY, invSize ); }\r\n\t\t\tp.prevZ = p.prev;\r\n\t\t\tp.nextZ = p.next;\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\tp.prevZ.nextZ = null;\r\n\t\tp.prevZ = null;\r\n\r\n\t\tsortLinked( p );\r\n\r\n\t}\r\n\r\n\t// Simon Tatham's linked list merge sort algorithm\r\n\t// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\r\n\tfunction sortLinked( list ) {\r\n\r\n\t\tvar i, p, q, e, tail, numMerges, pSize, qSize,\r\n\t\t\tinSize = 1;\r\n\r\n\t\tdo {\r\n\r\n\t\t\tp = list;\r\n\t\t\tlist = null;\r\n\t\t\ttail = null;\r\n\t\t\tnumMerges = 0;\r\n\r\n\t\t\twhile ( p ) {\r\n\r\n\t\t\t\tnumMerges ++;\r\n\t\t\t\tq = p;\r\n\t\t\t\tpSize = 0;\r\n\t\t\t\tfor ( i = 0; i < inSize; i ++ ) {\r\n\r\n\t\t\t\t\tpSize ++;\r\n\t\t\t\t\tq = q.nextZ;\r\n\t\t\t\t\tif ( ! q ) { break; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tqSize = inSize;\r\n\r\n\t\t\t\twhile ( pSize > 0 || ( qSize > 0 && q ) ) {\r\n\r\n\t\t\t\t\tif ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {\r\n\r\n\t\t\t\t\t\te = p;\r\n\t\t\t\t\t\tp = p.nextZ;\r\n\t\t\t\t\t\tpSize --;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\te = q;\r\n\t\t\t\t\t\tq = q.nextZ;\r\n\t\t\t\t\t\tqSize --;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( tail ) { tail.nextZ = e; }\r\n\t\t\t\t\telse { list = e; }\r\n\r\n\t\t\t\t\te.prevZ = tail;\r\n\t\t\t\t\ttail = e;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp = q;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttail.nextZ = null;\r\n\t\t\tinSize *= 2;\r\n\r\n\t\t} while ( numMerges > 1 );\r\n\r\n\t\treturn list;\r\n\r\n\t}\r\n\r\n\t// z-order of a point given coords and inverse of the longer side of data bbox\r\n\tfunction zOrder( x, y, minX, minY, invSize ) {\r\n\r\n\t\t// coords are transformed into non-negative 15-bit integer range\r\n\t\tx = 32767 * ( x - minX ) * invSize;\r\n\t\ty = 32767 * ( y - minY ) * invSize;\r\n\r\n\t\tx = ( x | ( x << 8 ) ) & 0x00FF00FF;\r\n\t\tx = ( x | ( x << 4 ) ) & 0x0F0F0F0F;\r\n\t\tx = ( x | ( x << 2 ) ) & 0x33333333;\r\n\t\tx = ( x | ( x << 1 ) ) & 0x55555555;\r\n\r\n\t\ty = ( y | ( y << 8 ) ) & 0x00FF00FF;\r\n\t\ty = ( y | ( y << 4 ) ) & 0x0F0F0F0F;\r\n\t\ty = ( y | ( y << 2 ) ) & 0x33333333;\r\n\t\ty = ( y | ( y << 1 ) ) & 0x55555555;\r\n\r\n\t\treturn x | ( y << 1 );\r\n\r\n\t}\r\n\r\n\t// find the leftmost node of a polygon ring\r\n\tfunction getLeftmost( start ) {\r\n\r\n\t\tvar p = start,\r\n\t\t\tleftmost = start;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) { leftmost = p; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\treturn leftmost;\r\n\r\n\t}\r\n\r\n\t// check if a point lies within a convex triangle\r\n\tfunction pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {\r\n\r\n\t\treturn ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&\r\n\t\t\t ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&\r\n\t\t\t ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;\r\n\r\n\t}\r\n\r\n\t// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\r\n\tfunction isValidDiagonal( a, b ) {\r\n\r\n\t\treturn a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&\r\n\t\t\t locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );\r\n\r\n\t}\r\n\r\n\t// signed area of a triangle\r\n\tfunction area( p, q, r ) {\r\n\r\n\t\treturn ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );\r\n\r\n\t}\r\n\r\n\t// check if two points are equal\r\n\tfunction equals( p1, p2 ) {\r\n\r\n\t\treturn p1.x === p2.x && p1.y === p2.y;\r\n\r\n\t}\r\n\r\n\t// check if two segments intersect\r\n\tfunction intersects( p1, q1, p2, q2 ) {\r\n\r\n\t\tif ( ( equals( p1, p2 ) && equals( q1, q2 ) ) ||\r\n\t\t\t( equals( p1, q2 ) && equals( p2, q1 ) ) ) { return true; }\r\n\t\treturn area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&\r\n\t\t\t area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;\r\n\r\n\t}\r\n\r\n\t// check if a polygon diagonal intersects any polygon segments\r\n\tfunction intersectsPolygon( a, b ) {\r\n\r\n\t\tvar p = a;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\r\n\t\t\t\t\tintersects( p, p.next, a, b ) ) { return true; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== a );\r\n\r\n\t\treturn false;\r\n\r\n\t}\r\n\r\n\t// check if a polygon diagonal is locally inside the polygon\r\n\tfunction locallyInside( a, b ) {\r\n\r\n\t\treturn area( a.prev, a, a.next ) < 0 ?\r\n\t\t\tarea( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :\r\n\t\t\tarea( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;\r\n\r\n\t}\r\n\r\n\t// check if the middle point of a polygon diagonal is inside the polygon\r\n\tfunction middleInside( a, b ) {\r\n\r\n\t\tvar p = a,\r\n\t\t\tinside = false,\r\n\t\t\tpx = ( a.x + b.x ) / 2,\r\n\t\t\tpy = ( a.y + b.y ) / 2;\r\n\t\tdo {\r\n\r\n\t\t\tif ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&\r\n\t\t\t\t\t( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )\r\n\t\t\t\t{ inside = ! inside; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== a );\r\n\r\n\t\treturn inside;\r\n\r\n\t}\r\n\r\n\t// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\r\n\t// if one belongs to the outer ring and another to a hole, it merges it into a single ring\r\n\tfunction splitPolygon( a, b ) {\r\n\r\n\t\tvar a2 = new Node( a.i, a.x, a.y ),\r\n\t\t\tb2 = new Node( b.i, b.x, b.y ),\r\n\t\t\tan = a.next,\r\n\t\t\tbp = b.prev;\r\n\r\n\t\ta.next = b;\r\n\t\tb.prev = a;\r\n\r\n\t\ta2.next = an;\r\n\t\tan.prev = a2;\r\n\r\n\t\tb2.next = a2;\r\n\t\ta2.prev = b2;\r\n\r\n\t\tbp.next = b2;\r\n\t\tb2.prev = bp;\r\n\r\n\t\treturn b2;\r\n\r\n\t}\r\n\r\n\t// create a node and optionally link it with previous one (in a circular doubly linked list)\r\n\tfunction insertNode( i, x, y, last ) {\r\n\r\n\t\tvar p = new Node( i, x, y );\r\n\r\n\t\tif ( ! last ) {\r\n\r\n\t\t\tp.prev = p;\r\n\t\t\tp.next = p;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tp.next = last.next;\r\n\t\t\tp.prev = last;\r\n\t\t\tlast.next.prev = p;\r\n\t\t\tlast.next = p;\r\n\r\n\t\t}\r\n\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\tfunction removeNode( p ) {\r\n\r\n\t\tp.next.prev = p.prev;\r\n\t\tp.prev.next = p.next;\r\n\r\n\t\tif ( p.prevZ ) { p.prevZ.nextZ = p.nextZ; }\r\n\t\tif ( p.nextZ ) { p.nextZ.prevZ = p.prevZ; }\r\n\r\n\t}\r\n\r\n\tfunction Node( i, x, y ) {\r\n\r\n\t\t// vertex index in coordinates array\r\n\t\tthis.i = i;\r\n\r\n\t\t// vertex coordinates\r\n\t\tthis.x = x;\r\n\t\tthis.y = y;\r\n\r\n\t\t// previous and next vertex nodes in a polygon ring\r\n\t\tthis.prev = null;\r\n\t\tthis.next = null;\r\n\r\n\t\t// z-order curve value\r\n\t\tthis.z = null;\r\n\r\n\t\t// previous and next nodes in z-order\r\n\t\tthis.prevZ = null;\r\n\t\tthis.nextZ = null;\r\n\r\n\t\t// indicates whether this is a steiner point\r\n\t\tthis.steiner = false;\r\n\r\n\t}\r\n\r\n\tfunction signedArea( data, start, end, dim ) {\r\n\r\n\t\tvar sum = 0;\r\n\t\tfor ( var i = start, j = end - dim; i < end; i += dim ) {\r\n\r\n\t\t\tsum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );\r\n\t\t\tj = i;\r\n\r\n\t\t}\r\n\r\n\t\treturn sum;\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t */\r\n\r\n\tvar ShapeUtils = {\r\n\r\n\t\t// calculate area of the contour polygon\r\n\r\n\t\tarea: function ( contour ) {\r\n\r\n\t\t\tvar n = contour.length;\r\n\t\t\tvar a = 0.0;\r\n\r\n\t\t\tfor ( var p = n - 1, q = 0; q < n; p = q ++ ) {\r\n\r\n\t\t\t\ta += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn a * 0.5;\r\n\r\n\t\t},\r\n\r\n\t\tisClockWise: function ( pts ) {\r\n\r\n\t\t\treturn ShapeUtils.area( pts ) < 0;\r\n\r\n\t\t},\r\n\r\n\t\ttriangulateShape: function ( contour, holes ) {\r\n\r\n\t\t\tvar vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]\r\n\t\t\tvar holeIndices = []; // array of hole indices\r\n\t\t\tvar faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]\r\n\r\n\t\t\tremoveDupEndPts( contour );\r\n\t\t\taddContour( vertices, contour );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar holeIndex = contour.length;\r\n\r\n\t\t\tholes.forEach( removeDupEndPts );\r\n\r\n\t\t\tfor ( var i = 0; i < holes.length; i ++ ) {\r\n\r\n\t\t\t\tholeIndices.push( holeIndex );\r\n\t\t\t\tholeIndex += holes[ i ].length;\r\n\t\t\t\taddContour( vertices, holes[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar triangles = Earcut.triangulate( vertices, holeIndices );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfor ( var i = 0; i < triangles.length; i += 3 ) {\r\n\r\n\t\t\t\tfaces.push( triangles.slice( i, i + 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn faces;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tfunction removeDupEndPts( points ) {\r\n\r\n\t\tvar l = points.length;\r\n\r\n\t\tif ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {\r\n\r\n\t\t\tpoints.pop();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction addContour( vertices, contour ) {\r\n\r\n\t\tfor ( var i = 0; i < contour.length; i ++ ) {\r\n\r\n\t\t\tvertices.push( contour[ i ].x );\r\n\t\t\tvertices.push( contour[ i ].y );\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t * Creates extruded geometry from a path shape.\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * curveSegments: , // number of points on the curves\r\n\t * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too\r\n\t * depth: , // Depth to extrude the shape\r\n\t *\r\n\t * bevelEnabled: , // turn on bevel\r\n\t * bevelThickness: , // how deep into the original shape bevel goes\r\n\t * bevelSize: , // how far from shape outline (including bevelOffset) is bevel\r\n\t * bevelOffset: , // how far from shape outline does bevel start\r\n\t * bevelSegments: , // number of bevel layers\r\n\t *\r\n\t * extrudePath: // curve to extrude shape along\r\n\t *\r\n\t * UVGenerator: // object that provides UV generator functions\r\n\t *\r\n\t * }\r\n\t */\r\n\r\n\t// ExtrudeGeometry\r\n\r\n\tfunction ExtrudeGeometry( shapes, options ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ExtrudeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\toptions: options\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tExtrudeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tExtrudeGeometry.prototype.constructor = ExtrudeGeometry;\r\n\r\n\tExtrudeGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Geometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\t\tvar options = this.parameters.options;\r\n\r\n\t\treturn toJSON( shapes, options, data );\r\n\r\n\t};\r\n\r\n\t// ExtrudeBufferGeometry\r\n\r\n\tfunction ExtrudeBufferGeometry( shapes, options ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ExtrudeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\toptions: options\r\n\t\t};\r\n\r\n\t\tshapes = Array.isArray( shapes ) ? shapes : [ shapes ];\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar verticesArray = [];\r\n\t\tvar uvArray = [];\r\n\r\n\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar shape = shapes[ i ];\r\n\t\t\taddShape( shape );\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );\r\n\r\n\t\tthis.computeVertexNormals();\r\n\r\n\t\t// functions\r\n\r\n\t\tfunction addShape( shape ) {\r\n\r\n\t\t\tvar placeholder = [];\r\n\r\n\t\t\t// options\r\n\r\n\t\t\tvar curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;\r\n\t\t\tvar steps = options.steps !== undefined ? options.steps : 1;\r\n\t\t\tvar depth = options.depth !== undefined ? options.depth : 100;\r\n\r\n\t\t\tvar bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;\r\n\t\t\tvar bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;\r\n\t\t\tvar bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;\r\n\t\t\tvar bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;\r\n\t\t\tvar bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;\r\n\r\n\t\t\tvar extrudePath = options.extrudePath;\r\n\r\n\t\t\tvar uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;\r\n\r\n\t\t\t// deprecated options\r\n\r\n\t\t\tif ( options.amount !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );\r\n\t\t\t\tdepth = options.amount;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar extrudePts, extrudeByPath = false;\r\n\t\t\tvar splineTube, binormal, normal, position2;\r\n\r\n\t\t\tif ( extrudePath ) {\r\n\r\n\t\t\t\textrudePts = extrudePath.getSpacedPoints( steps );\r\n\r\n\t\t\t\textrudeByPath = true;\r\n\t\t\t\tbevelEnabled = false; // bevels not supported for path extrusion\r\n\r\n\t\t\t\t// SETUP TNB variables\r\n\r\n\t\t\t\t// TODO1 - have a .isClosed in spline?\r\n\r\n\t\t\t\tsplineTube = extrudePath.computeFrenetFrames( steps, false );\r\n\r\n\t\t\t\t// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);\r\n\r\n\t\t\t\tbinormal = new Vector3();\r\n\t\t\t\tnormal = new Vector3();\r\n\t\t\t\tposition2 = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Safeguards if bevels are not enabled\r\n\r\n\t\t\tif ( ! bevelEnabled ) {\r\n\r\n\t\t\t\tbevelSegments = 0;\r\n\t\t\t\tbevelThickness = 0;\r\n\t\t\t\tbevelSize = 0;\r\n\t\t\t\tbevelOffset = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Variables initialization\r\n\r\n\t\t\tvar ahole, h, hl; // looping of holes\r\n\r\n\t\t\tvar shapePoints = shape.extractPoints( curveSegments );\r\n\r\n\t\t\tvar vertices = shapePoints.shape;\r\n\t\t\tvar holes = shapePoints.holes;\r\n\r\n\t\t\tvar reverse = ! ShapeUtils.isClockWise( vertices );\r\n\r\n\t\t\tif ( reverse ) {\r\n\r\n\t\t\t\tvertices = vertices.reverse();\r\n\r\n\t\t\t\t// Maybe we should also check if holes are in the opposite direction, just to be safe ...\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\t\tif ( ShapeUtils.isClockWise( ahole ) ) {\r\n\r\n\t\t\t\t\t\tholes[ h ] = ahole.reverse();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar faces = ShapeUtils.triangulateShape( vertices, holes );\r\n\r\n\t\t\t/* Vertices */\r\n\r\n\t\t\tvar contour = vertices; // vertices has all points but contour has only points of circumference\r\n\r\n\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\tvertices = vertices.concat( ahole );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction scalePt2( pt, vec, size ) {\r\n\r\n\t\t\t\tif ( ! vec ) { console.error( \"THREE.ExtrudeGeometry: vec does not exist\" ); }\r\n\r\n\t\t\t\treturn vec.clone().multiplyScalar( size ).add( pt );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar b, bs, t, z,\r\n\t\t\t\tvert, vlen = vertices.length,\r\n\t\t\t\tface, flen = faces.length;\r\n\r\n\r\n\t\t\t// Find directions for point movement\r\n\r\n\r\n\t\t\tfunction getBevelVec( inPt, inPrev, inNext ) {\r\n\r\n\t\t\t\t// computes for inPt the corresponding point inPt' on a new contour\r\n\t\t\t\t// shifted by 1 unit (length of normalized vector) to the left\r\n\t\t\t\t// if we walk along contour clockwise, this new contour is outside the old one\r\n\t\t\t\t//\r\n\t\t\t\t// inPt' is the intersection of the two lines parallel to the two\r\n\t\t\t\t// adjacent edges of inPt at a distance of 1 unit on the left side.\r\n\r\n\t\t\t\tvar v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt\r\n\r\n\t\t\t\t// good reading for geometry algorithms (here: line-line intersection)\r\n\t\t\t\t// http://geomalgorithms.com/a05-_intersect-1.html\r\n\r\n\t\t\t\tvar v_prev_x = inPt.x - inPrev.x,\r\n\t\t\t\t\tv_prev_y = inPt.y - inPrev.y;\r\n\t\t\t\tvar v_next_x = inNext.x - inPt.x,\r\n\t\t\t\t\tv_next_y = inNext.y - inPt.y;\r\n\r\n\t\t\t\tvar v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );\r\n\r\n\t\t\t\t// check for collinear edges\r\n\t\t\t\tvar collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );\r\n\r\n\t\t\t\tif ( Math.abs( collinear0 ) > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t// not collinear\r\n\r\n\t\t\t\t\t// length of vectors for normalizing\r\n\r\n\t\t\t\t\tvar v_prev_len = Math.sqrt( v_prev_lensq );\r\n\t\t\t\t\tvar v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );\r\n\r\n\t\t\t\t\t// shift adjacent points by unit vectors to the left\r\n\r\n\t\t\t\t\tvar ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );\r\n\t\t\t\t\tvar ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );\r\n\r\n\t\t\t\t\tvar ptNextShift_x = ( inNext.x - v_next_y / v_next_len );\r\n\t\t\t\t\tvar ptNextShift_y = ( inNext.y + v_next_x / v_next_len );\r\n\r\n\t\t\t\t\t// scaling factor for v_prev to intersection point\r\n\r\n\t\t\t\t\tvar sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -\r\n\t\t\t\t\t\t\t( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /\r\n\t\t\t\t\t\t( v_prev_x * v_next_y - v_prev_y * v_next_x );\r\n\r\n\t\t\t\t\t// vector from inPt to intersection point\r\n\r\n\t\t\t\t\tv_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );\r\n\t\t\t\t\tv_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );\r\n\r\n\t\t\t\t\t// Don't normalize!, otherwise sharp corners become ugly\r\n\t\t\t\t\t// but prevent crazy spikes\r\n\t\t\t\t\tvar v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );\r\n\t\t\t\t\tif ( v_trans_lensq <= 2 ) {\r\n\r\n\t\t\t\t\t\treturn new Vector2( v_trans_x, v_trans_y );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_trans_lensq / 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// handle special case of collinear edges\r\n\r\n\t\t\t\t\tvar direction_eq = false; // assumes: opposite\r\n\t\t\t\t\tif ( v_prev_x > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\tif ( v_next_x > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( v_prev_x < - Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\tif ( v_next_x < - Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tif ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {\r\n\r\n\t\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( direction_eq ) {\r\n\r\n\t\t\t\t\t\t// console.log(\"Warning: lines are a straight sequence\");\r\n\t\t\t\t\t\tv_trans_x = - v_prev_y;\r\n\t\t\t\t\t\tv_trans_y = v_prev_x;\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_prev_lensq );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// console.log(\"Warning: lines are a straight spike\");\r\n\t\t\t\t\t\tv_trans_x = v_prev_x;\r\n\t\t\t\t\t\tv_trans_y = v_prev_y;\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_prev_lensq / 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar contourMovements = [];\r\n\r\n\t\t\tfor ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {\r\n\r\n\t\t\t\tif ( j === il ) { j = 0; }\r\n\t\t\t\tif ( k === il ) { k = 0; }\r\n\r\n\t\t\t\t// (j)---(i)---(k)\r\n\t\t\t\t// console.log('i,j,k', i, j , k)\r\n\r\n\t\t\t\tcontourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar holesMovements = [],\r\n\t\t\t\toneHoleMovements, verticesMovements = contourMovements.concat();\r\n\r\n\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\toneHoleMovements = [];\r\n\r\n\t\t\t\tfor ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {\r\n\r\n\t\t\t\t\tif ( j === il ) { j = 0; }\r\n\t\t\t\t\tif ( k === il ) { k = 0; }\r\n\r\n\t\t\t\t\t// (j)---(i)---(k)\r\n\t\t\t\t\toneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tholesMovements.push( oneHoleMovements );\r\n\t\t\t\tverticesMovements = verticesMovements.concat( oneHoleMovements );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Loop bevelSegments, 1 for the front, 1 for the back\r\n\r\n\t\t\tfor ( b = 0; b < bevelSegments; b ++ ) {\r\n\r\n\t\t\t\t//for ( b = bevelSegments; b > 0; b -- ) {\r\n\r\n\t\t\t\tt = b / bevelSegments;\r\n\t\t\t\tz = bevelThickness * Math.cos( t * Math.PI / 2 );\r\n\t\t\t\tbs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;\r\n\r\n\t\t\t\t// contract shape\r\n\r\n\t\t\t\tfor ( i = 0, il = contour.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvert = scalePt2( contour[ i ], contourMovements[ i ], bs );\r\n\r\n\t\t\t\t\tv( vert.x, vert.y, - z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// expand holes\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\toneHoleMovements = holesMovements[ h ];\r\n\r\n\t\t\t\t\tfor ( i = 0, il = ahole.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );\r\n\r\n\t\t\t\t\t\tv( vert.x, vert.y, - z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbs = bevelSize + bevelOffset;\r\n\r\n\t\t\t// Back facing vertices\r\n\r\n\t\t\tfor ( i = 0; i < vlen; i ++ ) {\r\n\r\n\t\t\t\tvert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];\r\n\r\n\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\tv( vert.x, vert.y, 0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );\r\n\r\n\t\t\t\t\tnormal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );\r\n\t\t\t\t\tbinormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );\r\n\r\n\t\t\t\t\tposition2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );\r\n\r\n\t\t\t\t\tv( position2.x, position2.y, position2.z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Add stepped vertices...\r\n\t\t\t// Including front facing vertices\r\n\r\n\t\t\tvar s;\r\n\r\n\t\t\tfor ( s = 1; s <= steps; s ++ ) {\r\n\r\n\t\t\t\tfor ( i = 0; i < vlen; i ++ ) {\r\n\r\n\t\t\t\t\tvert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];\r\n\r\n\t\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\t\tv( vert.x, vert.y, depth / steps * s );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );\r\n\r\n\t\t\t\t\t\tnormal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );\r\n\t\t\t\t\t\tbinormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );\r\n\r\n\t\t\t\t\t\tposition2.copy( extrudePts[ s ] ).add( normal ).add( binormal );\r\n\r\n\t\t\t\t\t\tv( position2.x, position2.y, position2.z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Add bevel segments planes\r\n\r\n\t\t\t//for ( b = 1; b <= bevelSegments; b ++ ) {\r\n\t\t\tfor ( b = bevelSegments - 1; b >= 0; b -- ) {\r\n\r\n\t\t\t\tt = b / bevelSegments;\r\n\t\t\t\tz = bevelThickness * Math.cos( t * Math.PI / 2 );\r\n\t\t\t\tbs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;\r\n\r\n\t\t\t\t// contract shape\r\n\r\n\t\t\t\tfor ( i = 0, il = contour.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvert = scalePt2( contour[ i ], contourMovements[ i ], bs );\r\n\t\t\t\t\tv( vert.x, vert.y, depth + z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// expand holes\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\toneHoleMovements = holesMovements[ h ];\r\n\r\n\t\t\t\t\tfor ( i = 0, il = ahole.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );\r\n\r\n\t\t\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\t\t\tv( vert.x, vert.y, depth + z );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tv( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t/* Faces */\r\n\r\n\t\t\t// Top and bottom faces\r\n\r\n\t\t\tbuildLidFaces();\r\n\r\n\t\t\t// Sides faces\r\n\r\n\t\t\tbuildSideFaces();\r\n\r\n\r\n\t\t\t///// Internal functions\r\n\r\n\t\t\tfunction buildLidFaces() {\r\n\r\n\t\t\t\tvar start = verticesArray.length / 3;\r\n\r\n\t\t\t\tif ( bevelEnabled ) {\r\n\r\n\t\t\t\t\tvar layer = 0; // steps + 1\r\n\t\t\t\t\tvar offset = vlen * layer;\r\n\r\n\t\t\t\t\t// Bottom faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlayer = steps + bevelSegments * 2;\r\n\t\t\t\t\toffset = vlen * layer;\r\n\r\n\t\t\t\t\t// Top faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// Bottom faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 2 ], face[ 1 ], face[ 0 ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Top faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.addGroup( start, verticesArray.length / 3 - start, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Create faces for the z-sides of the shape\r\n\r\n\t\t\tfunction buildSideFaces() {\r\n\r\n\t\t\t\tvar start = verticesArray.length / 3;\r\n\t\t\t\tvar layeroffset = 0;\r\n\t\t\t\tsidewalls( contour, layeroffset );\r\n\t\t\t\tlayeroffset += contour.length;\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\tsidewalls( ahole, layeroffset );\r\n\r\n\t\t\t\t\t//, true\r\n\t\t\t\t\tlayeroffset += ahole.length;\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tscope.addGroup( start, verticesArray.length / 3 - start, 1 );\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction sidewalls( contour, layeroffset ) {\r\n\r\n\t\t\t\tvar j, k;\r\n\t\t\t\ti = contour.length;\r\n\r\n\t\t\t\twhile ( -- i >= 0 ) {\r\n\r\n\t\t\t\t\tj = i;\r\n\t\t\t\t\tk = i - 1;\r\n\t\t\t\t\tif ( k < 0 ) { k = contour.length - 1; }\r\n\r\n\t\t\t\t\t//console.log('b', i,j, i-1, k,vertices.length);\r\n\r\n\t\t\t\t\tvar s = 0,\r\n\t\t\t\t\t\tsl = steps + bevelSegments * 2;\r\n\r\n\t\t\t\t\tfor ( s = 0; s < sl; s ++ ) {\r\n\r\n\t\t\t\t\t\tvar slen1 = vlen * s;\r\n\t\t\t\t\t\tvar slen2 = vlen * ( s + 1 );\r\n\r\n\t\t\t\t\t\tvar a = layeroffset + j + slen1,\r\n\t\t\t\t\t\t\tb = layeroffset + k + slen1,\r\n\t\t\t\t\t\t\tc = layeroffset + k + slen2,\r\n\t\t\t\t\t\t\td = layeroffset + j + slen2;\r\n\r\n\t\t\t\t\t\tf4( a, b, c, d );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction v( x, y, z ) {\r\n\r\n\t\t\t\tplaceholder.push( x );\r\n\t\t\t\tplaceholder.push( y );\r\n\t\t\t\tplaceholder.push( z );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction f3( a, b, c ) {\r\n\r\n\t\t\t\taddVertex( a );\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( c );\r\n\r\n\t\t\t\tvar nextIndex = verticesArray.length / 3;\r\n\t\t\t\tvar uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );\r\n\r\n\t\t\t\taddUV( uvs[ 0 ] );\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 2 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction f4( a, b, c, d ) {\r\n\r\n\t\t\t\taddVertex( a );\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( d );\r\n\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( c );\r\n\t\t\t\taddVertex( d );\r\n\r\n\r\n\t\t\t\tvar nextIndex = verticesArray.length / 3;\r\n\t\t\t\tvar uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );\r\n\r\n\t\t\t\taddUV( uvs[ 0 ] );\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 3 ] );\r\n\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 2 ] );\r\n\t\t\t\taddUV( uvs[ 3 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction addVertex( index ) {\r\n\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 0 ] );\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 1 ] );\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 2 ] );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction addUV( vector2 ) {\r\n\r\n\t\t\t\tuvArray.push( vector2.x );\r\n\t\t\t\tuvArray.push( vector2.y );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;\r\n\r\n\tExtrudeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\t\tvar options = this.parameters.options;\r\n\r\n\t\treturn toJSON( shapes, options, data );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar WorldUVGenerator = {\r\n\r\n\t\tgenerateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {\r\n\r\n\t\t\tvar a_x = vertices[ indexA * 3 ];\r\n\t\t\tvar a_y = vertices[ indexA * 3 + 1 ];\r\n\t\t\tvar b_x = vertices[ indexB * 3 ];\r\n\t\t\tvar b_y = vertices[ indexB * 3 + 1 ];\r\n\t\t\tvar c_x = vertices[ indexC * 3 ];\r\n\t\t\tvar c_y = vertices[ indexC * 3 + 1 ];\r\n\r\n\t\t\treturn [\r\n\t\t\t\tnew Vector2( a_x, a_y ),\r\n\t\t\t\tnew Vector2( b_x, b_y ),\r\n\t\t\t\tnew Vector2( c_x, c_y )\r\n\t\t\t];\r\n\r\n\t\t},\r\n\r\n\t\tgenerateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {\r\n\r\n\t\t\tvar a_x = vertices[ indexA * 3 ];\r\n\t\t\tvar a_y = vertices[ indexA * 3 + 1 ];\r\n\t\t\tvar a_z = vertices[ indexA * 3 + 2 ];\r\n\t\t\tvar b_x = vertices[ indexB * 3 ];\r\n\t\t\tvar b_y = vertices[ indexB * 3 + 1 ];\r\n\t\t\tvar b_z = vertices[ indexB * 3 + 2 ];\r\n\t\t\tvar c_x = vertices[ indexC * 3 ];\r\n\t\t\tvar c_y = vertices[ indexC * 3 + 1 ];\r\n\t\t\tvar c_z = vertices[ indexC * 3 + 2 ];\r\n\t\t\tvar d_x = vertices[ indexD * 3 ];\r\n\t\t\tvar d_y = vertices[ indexD * 3 + 1 ];\r\n\t\t\tvar d_z = vertices[ indexD * 3 + 2 ];\r\n\r\n\t\t\tif ( Math.abs( a_y - b_y ) < 0.01 ) {\r\n\r\n\t\t\t\treturn [\r\n\t\t\t\t\tnew Vector2( a_x, 1 - a_z ),\r\n\t\t\t\t\tnew Vector2( b_x, 1 - b_z ),\r\n\t\t\t\t\tnew Vector2( c_x, 1 - c_z ),\r\n\t\t\t\t\tnew Vector2( d_x, 1 - d_z )\r\n\t\t\t\t];\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn [\r\n\t\t\t\t\tnew Vector2( a_y, 1 - a_z ),\r\n\t\t\t\t\tnew Vector2( b_y, 1 - b_z ),\r\n\t\t\t\t\tnew Vector2( c_y, 1 - c_z ),\r\n\t\t\t\t\tnew Vector2( d_y, 1 - d_z )\r\n\t\t\t\t];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t};\r\n\r\n\tfunction toJSON( shapes, options, data ) {\r\n\r\n\t\t//\r\n\r\n\t\tdata.shapes = [];\r\n\r\n\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\tdata.shapes.push( shape.uuid );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tdata.shapes.push( shapes.uuid );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tif ( options.extrudePath !== undefined ) { data.options.extrudePath = options.extrudePath.toJSON(); }\r\n\r\n\t\treturn data;\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * Text = 3D Text\r\n\t *\r\n\t * parameters = {\r\n\t * font: , // font\r\n\t *\r\n\t * size: , // size of the text\r\n\t * height: , // thickness to extrude text\r\n\t * curveSegments: , // number of points on the curves\r\n\t *\r\n\t * bevelEnabled: , // turn on bevel\r\n\t * bevelThickness: , // how deep into text bevel goes\r\n\t * bevelSize: , // how far from text outline (including bevelOffset) is bevel\r\n\t * bevelOffset: // how far from text outline does bevel start\r\n\t * }\r\n\t */\r\n\r\n\t// TextGeometry\r\n\r\n\tfunction TextGeometry( text, parameters ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TextGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\ttext: text,\r\n\t\t\tparameters: parameters\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTextGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTextGeometry.prototype.constructor = TextGeometry;\r\n\r\n\t// TextBufferGeometry\r\n\r\n\tfunction TextBufferGeometry( text, parameters ) {\r\n\r\n\t\tparameters = parameters || {};\r\n\r\n\t\tvar font = parameters.font;\r\n\r\n\t\tif ( ! ( font && font.isFont ) ) {\r\n\r\n\t\t\tconsole.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );\r\n\t\t\treturn new Geometry();\r\n\r\n\t\t}\r\n\r\n\t\tvar shapes = font.generateShapes( text, parameters.size );\r\n\r\n\t\t// translate parameters to ExtrudeGeometry API\r\n\r\n\t\tparameters.depth = parameters.height !== undefined ? parameters.height : 50;\r\n\r\n\t\t// defaults\r\n\r\n\t\tif ( parameters.bevelThickness === undefined ) { parameters.bevelThickness = 10; }\r\n\t\tif ( parameters.bevelSize === undefined ) { parameters.bevelSize = 8; }\r\n\t\tif ( parameters.bevelEnabled === undefined ) { parameters.bevelEnabled = false; }\r\n\r\n\t\tExtrudeBufferGeometry.call( this, shapes, parameters );\r\n\r\n\t\tthis.type = 'TextBufferGeometry';\r\n\r\n\t}\r\n\r\n\tTextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );\r\n\tTextBufferGeometry.prototype.constructor = TextBufferGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// SphereGeometry\r\n\r\n\tfunction SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'SphereGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tSphereGeometry.prototype = Object.create( Geometry.prototype );\r\n\tSphereGeometry.prototype.constructor = SphereGeometry;\r\n\r\n\t// SphereBufferGeometry\r\n\r\n\tfunction SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'SphereBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\r\n\t\twidthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );\r\n\t\theightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );\r\n\r\n\t\tphiStart = phiStart !== undefined ? phiStart : 0;\r\n\t\tphiLength = phiLength !== undefined ? phiLength : Math.PI * 2;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI;\r\n\r\n\t\tvar thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );\r\n\r\n\t\tvar ix, iy;\r\n\r\n\t\tvar index = 0;\r\n\t\tvar grid = [];\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( iy = 0; iy <= heightSegments; iy ++ ) {\r\n\r\n\t\t\tvar verticesRow = [];\r\n\r\n\t\t\tvar v = iy / heightSegments;\r\n\r\n\t\t\t// special case for the poles\r\n\r\n\t\t\tvar uOffset = 0;\r\n\r\n\t\t\tif ( iy == 0 && thetaStart == 0 ) {\r\n\r\n\t\t\t\tuOffset = 0.5 / widthSegments;\r\n\r\n\t\t\t} else if ( iy == heightSegments && thetaEnd == Math.PI ) {\r\n\r\n\t\t\t\tuOffset = - 0.5 / widthSegments;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( ix = 0; ix <= widthSegments; ix ++ ) {\r\n\r\n\t\t\t\tvar u = ix / widthSegments;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );\r\n\t\t\t\tvertex.y = radius * Math.cos( thetaStart + v * thetaLength );\r\n\t\t\t\tvertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormal.copy( vertex ).normalize();\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( u + uOffset, 1 - v );\r\n\r\n\t\t\t\tverticesRow.push( index ++ );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgrid.push( verticesRow );\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( iy = 0; iy < heightSegments; iy ++ ) {\r\n\r\n\t\t\tfor ( ix = 0; ix < widthSegments; ix ++ ) {\r\n\r\n\t\t\t\tvar a = grid[ iy ][ ix + 1 ];\r\n\t\t\t\tvar b = grid[ iy ][ ix ];\r\n\t\t\t\tvar c = grid[ iy + 1 ][ ix ];\r\n\t\t\t\tvar d = grid[ iy + 1 ][ ix + 1 ];\r\n\r\n\t\t\t\tif ( iy !== 0 || thetaStart > 0 ) { indices.push( a, b, d ); }\r\n\t\t\t\tif ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) { indices.push( b, c, d ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tSphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tSphereBufferGeometry.prototype.constructor = SphereBufferGeometry;\n\n\t/**\r\n\t * @author Kaleb Murphy\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// RingGeometry\r\n\r\n\tfunction RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'RingGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tinnerRadius: innerRadius,\r\n\t\t\touterRadius: outerRadius,\r\n\t\t\tthetaSegments: thetaSegments,\r\n\t\t\tphiSegments: phiSegments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tRingGeometry.prototype = Object.create( Geometry.prototype );\r\n\tRingGeometry.prototype.constructor = RingGeometry;\r\n\r\n\t// RingBufferGeometry\r\n\r\n\tfunction RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'RingBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tinnerRadius: innerRadius,\r\n\t\t\touterRadius: outerRadius,\r\n\t\t\tthetaSegments: thetaSegments,\r\n\t\t\tphiSegments: phiSegments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tinnerRadius = innerRadius || 0.5;\r\n\t\touterRadius = outerRadius || 1;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\tthetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;\r\n\t\tphiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// some helper variables\r\n\r\n\t\tvar segment;\r\n\t\tvar radius = innerRadius;\r\n\t\tvar radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar j, i;\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( j = 0; j <= phiSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 0; i <= thetaSegments; i ++ ) {\r\n\r\n\t\t\t\t// values are generate from the inside of the ring to the outside\r\n\r\n\t\t\t\tsegment = thetaStart + i / thetaSegments * thetaLength;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = radius * Math.cos( segment );\r\n\t\t\t\tvertex.y = radius * Math.sin( segment );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = ( vertex.x / outerRadius + 1 ) / 2;\r\n\t\t\t\tuv.y = ( vertex.y / outerRadius + 1 ) / 2;\r\n\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// increase the radius for next row of vertices\r\n\r\n\t\t\tradius += radiusStep;\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( j = 0; j < phiSegments; j ++ ) {\r\n\r\n\t\t\tvar thetaSegmentLevel = j * ( thetaSegments + 1 );\r\n\r\n\t\t\tfor ( i = 0; i < thetaSegments; i ++ ) {\r\n\r\n\t\t\t\tsegment = i + thetaSegmentLevel;\r\n\r\n\t\t\t\tvar a = segment;\r\n\t\t\t\tvar b = segment + thetaSegments + 1;\r\n\t\t\t\tvar c = segment + thetaSegments + 2;\r\n\t\t\t\tvar d = segment + 1;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tRingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tRingBufferGeometry.prototype.constructor = RingBufferGeometry;\n\n\t/**\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author bhouston / http://clara.io\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// LatheGeometry\r\n\r\n\tfunction LatheGeometry( points, segments, phiStart, phiLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'LatheGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpoints: points,\r\n\t\t\tsegments: segments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tLatheGeometry.prototype = Object.create( Geometry.prototype );\r\n\tLatheGeometry.prototype.constructor = LatheGeometry;\r\n\r\n\t// LatheBufferGeometry\r\n\r\n\tfunction LatheBufferGeometry( points, segments, phiStart, phiLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'LatheBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpoints: points,\r\n\t\t\tsegments: segments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength\r\n\t\t};\r\n\r\n\t\tsegments = Math.floor( segments ) || 12;\r\n\t\tphiStart = phiStart || 0;\r\n\t\tphiLength = phiLength || Math.PI * 2;\r\n\r\n\t\t// clamp phiLength so it's in range of [ 0, 2PI ]\r\n\r\n\t\tphiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );\r\n\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar base;\r\n\t\tvar inverseSegments = 1.0 / segments;\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar i, j;\r\n\r\n\t\t// generate vertices and uvs\r\n\r\n\t\tfor ( i = 0; i <= segments; i ++ ) {\r\n\r\n\t\t\tvar phi = phiStart + i * inverseSegments * phiLength;\r\n\r\n\t\t\tvar sin = Math.sin( phi );\r\n\t\t\tvar cos = Math.cos( phi );\r\n\r\n\t\t\tfor ( j = 0; j <= ( points.length - 1 ); j ++ ) {\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = points[ j ].x * sin;\r\n\t\t\t\tvertex.y = points[ j ].y;\r\n\t\t\t\tvertex.z = points[ j ].x * cos;\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = i / segments;\r\n\t\t\t\tuv.y = j / ( points.length - 1 );\r\n\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( i = 0; i < segments; i ++ ) {\r\n\r\n\t\t\tfor ( j = 0; j < ( points.length - 1 ); j ++ ) {\r\n\r\n\t\t\t\tbase = j + i * points.length;\r\n\r\n\t\t\t\tvar a = base;\r\n\t\t\t\tvar b = base + points.length;\r\n\t\t\t\tvar c = base + points.length + 1;\r\n\t\t\t\tvar d = base + 1;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// generate normals\r\n\r\n\t\tthis.computeVertexNormals();\r\n\r\n\t\t// if the geometry is closed, we need to average the normals along the seam.\r\n\t\t// because the corresponding vertices are identical (but still have different UVs).\r\n\r\n\t\tif ( phiLength === Math.PI * 2 ) {\r\n\r\n\t\t\tvar normals = this.attributes.normal.array;\r\n\t\t\tvar n1 = new Vector3();\r\n\t\t\tvar n2 = new Vector3();\r\n\t\t\tvar n = new Vector3();\r\n\r\n\t\t\t// this is the buffer offset for the last line of vertices\r\n\r\n\t\t\tbase = segments * points.length * 3;\r\n\r\n\t\t\tfor ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {\r\n\r\n\t\t\t\t// select the normal of the vertex in the first line\r\n\r\n\t\t\t\tn1.x = normals[ j + 0 ];\r\n\t\t\t\tn1.y = normals[ j + 1 ];\r\n\t\t\t\tn1.z = normals[ j + 2 ];\r\n\r\n\t\t\t\t// select the normal of the vertex in the last line\r\n\r\n\t\t\t\tn2.x = normals[ base + j + 0 ];\r\n\t\t\t\tn2.y = normals[ base + j + 1 ];\r\n\t\t\t\tn2.z = normals[ base + j + 2 ];\r\n\r\n\t\t\t\t// average normals\r\n\r\n\t\t\t\tn.addVectors( n1, n2 ).normalize();\r\n\r\n\t\t\t\t// assign the new values to both normals\r\n\r\n\t\t\t\tnormals[ j + 0 ] = normals[ base + j + 0 ] = n.x;\r\n\t\t\t\tnormals[ j + 1 ] = normals[ base + j + 1 ] = n.y;\r\n\t\t\t\tnormals[ j + 2 ] = normals[ base + j + 2 ] = n.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tLatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tLatheBufferGeometry.prototype.constructor = LatheBufferGeometry;\n\n\t/**\r\n\t * @author jonobr1 / http://jonobr1.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// ShapeGeometry\r\n\r\n\tfunction ShapeGeometry( shapes, curveSegments ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ShapeGeometry';\r\n\r\n\t\tif ( typeof curveSegments === 'object' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );\r\n\r\n\t\t\tcurveSegments = curveSegments.curveSegments;\r\n\r\n\t\t}\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\tcurveSegments: curveSegments\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tShapeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tShapeGeometry.prototype.constructor = ShapeGeometry;\r\n\r\n\tShapeGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Geometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\r\n\t\treturn toJSON$1( shapes, data );\r\n\r\n\t};\r\n\r\n\t// ShapeBufferGeometry\r\n\r\n\tfunction ShapeBufferGeometry( shapes, curveSegments ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ShapeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\tcurveSegments: curveSegments\r\n\t\t};\r\n\r\n\t\tcurveSegments = curveSegments || 12;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar groupStart = 0;\r\n\t\tvar groupCount = 0;\r\n\r\n\t\t// allow single and array values for \"shapes\" parameter\r\n\r\n\t\tif ( Array.isArray( shapes ) === false ) {\r\n\r\n\t\t\taddShape( shapes );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tfor ( var i = 0; i < shapes.length; i ++ ) {\r\n\r\n\t\t\t\taddShape( shapes[ i ] );\r\n\r\n\t\t\t\tthis.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support\r\n\r\n\t\t\t\tgroupStart += groupCount;\r\n\t\t\t\tgroupCount = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\r\n\t\t// helper functions\r\n\r\n\t\tfunction addShape( shape ) {\r\n\r\n\t\t\tvar i, l, shapeHole;\r\n\r\n\t\t\tvar indexOffset = vertices.length / 3;\r\n\t\t\tvar points = shape.extractPoints( curveSegments );\r\n\r\n\t\t\tvar shapeVertices = points.shape;\r\n\t\t\tvar shapeHoles = points.holes;\r\n\r\n\t\t\t// check direction of vertices\r\n\r\n\t\t\tif ( ShapeUtils.isClockWise( shapeVertices ) === false ) {\r\n\r\n\t\t\t\tshapeVertices = shapeVertices.reverse();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( i = 0, l = shapeHoles.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tshapeHole = shapeHoles[ i ];\r\n\r\n\t\t\t\tif ( ShapeUtils.isClockWise( shapeHole ) === true ) {\r\n\r\n\t\t\t\t\tshapeHoles[ i ] = shapeHole.reverse();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );\r\n\r\n\t\t\t// join vertices of inner and outer paths to a single array\r\n\r\n\t\t\tfor ( i = 0, l = shapeHoles.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tshapeHole = shapeHoles[ i ];\r\n\t\t\t\tshapeVertices = shapeVertices.concat( shapeHole );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// vertices, normals, uvs\r\n\r\n\t\t\tfor ( i = 0, l = shapeVertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = shapeVertices[ i ];\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, 0 );\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\t\t\t\tuvs.push( vertex.x, vertex.y ); // world uvs\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// incides\r\n\r\n\t\t\tfor ( i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tvar a = face[ 0 ] + indexOffset;\r\n\t\t\t\tvar b = face[ 1 ] + indexOffset;\r\n\t\t\t\tvar c = face[ 2 ] + indexOffset;\r\n\r\n\t\t\t\tindices.push( a, b, c );\r\n\t\t\t\tgroupCount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;\r\n\r\n\tShapeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\r\n\t\treturn toJSON$1( shapes, data );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction toJSON$1( shapes, data ) {\r\n\r\n\t\tdata.shapes = [];\r\n\r\n\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\tdata.shapes.push( shape.uuid );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tdata.shapes.push( shapes.uuid );\r\n\r\n\t\t}\r\n\r\n\t\treturn data;\r\n\r\n\t}\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction EdgesGeometry( geometry, thresholdAngle ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'EdgesGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tthresholdAngle: thresholdAngle\r\n\t\t};\r\n\r\n\t\tthresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );\r\n\t\tvar edge = [ 0, 0 ], edges = {}, edge1, edge2;\r\n\t\tvar key, keys = [ 'a', 'b', 'c' ];\r\n\r\n\t\t// prepare source geometry\r\n\r\n\t\tvar geometry2;\r\n\r\n\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\tgeometry2 = new Geometry();\r\n\t\t\tgeometry2.fromBufferGeometry( geometry );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tgeometry2 = geometry.clone();\r\n\r\n\t\t}\r\n\r\n\t\tgeometry2.mergeVertices();\r\n\t\tgeometry2.computeFaceNormals();\r\n\r\n\t\tvar sourceVertices = geometry2.vertices;\r\n\t\tvar faces = geometry2.faces;\r\n\r\n\t\t// now create a data structure where each entry represents an edge with its adjoining faces\r\n\r\n\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\tfor ( var j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\tedge1 = face[ keys[ j ] ];\r\n\t\t\t\tedge2 = face[ keys[ ( j + 1 ) % 3 ] ];\r\n\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 );\r\n\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tedges[ key ].face2 = i;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate vertices\r\n\r\n\t\tfor ( key in edges ) {\r\n\r\n\t\t\tvar e = edges[ key ];\r\n\r\n\t\t\t// an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.\r\n\r\n\t\t\tif ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {\r\n\r\n\t\t\t\tvar vertex = sourceVertices[ e.index1 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\tvertex = sourceVertices[ e.index2 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\r\n\t}\r\n\r\n\tEdgesGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tEdgesGeometry.prototype.constructor = EdgesGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// CylinderGeometry\r\n\r\n\tfunction CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'CylinderGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradiusTop: radiusTop,\r\n\t\t\tradiusBottom: radiusBottom,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tCylinderGeometry.prototype = Object.create( Geometry.prototype );\r\n\tCylinderGeometry.prototype.constructor = CylinderGeometry;\r\n\r\n\t// CylinderBufferGeometry\r\n\r\n\tfunction CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'CylinderBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradiusTop: radiusTop,\r\n\t\t\tradiusBottom: radiusBottom,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tradiusTop = radiusTop !== undefined ? radiusTop : 1;\r\n\t\tradiusBottom = radiusBottom !== undefined ? radiusBottom : 1;\r\n\t\theight = height || 1;\r\n\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\theightSegments = Math.floor( heightSegments ) || 1;\r\n\r\n\t\topenEnded = openEnded !== undefined ? openEnded : false;\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0.0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar index = 0;\r\n\t\tvar indexArray = [];\r\n\t\tvar halfHeight = height / 2;\r\n\t\tvar groupStart = 0;\r\n\r\n\t\t// generate geometry\r\n\r\n\t\tgenerateTorso();\r\n\r\n\t\tif ( openEnded === false ) {\r\n\r\n\t\t\tif ( radiusTop > 0 ) { generateCap( true ); }\r\n\t\t\tif ( radiusBottom > 0 ) { generateCap( false ); }\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\tfunction generateTorso() {\r\n\r\n\t\t\tvar x, y;\r\n\t\t\tvar normal = new Vector3();\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tvar groupCount = 0;\r\n\r\n\t\t\t// this will be used to calculate the normal\r\n\t\t\tvar slope = ( radiusBottom - radiusTop ) / height;\r\n\r\n\t\t\t// generate vertices, normals and uvs\r\n\r\n\t\t\tfor ( y = 0; y <= heightSegments; y ++ ) {\r\n\r\n\t\t\t\tvar indexRow = [];\r\n\r\n\t\t\t\tvar v = y / heightSegments;\r\n\r\n\t\t\t\t// calculate the radius of the current row\r\n\r\n\t\t\t\tvar radius = v * ( radiusBottom - radiusTop ) + radiusTop;\r\n\r\n\t\t\t\tfor ( x = 0; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\t\tvar u = x / radialSegments;\r\n\r\n\t\t\t\t\tvar theta = u * thetaLength + thetaStart;\r\n\r\n\t\t\t\t\tvar sinTheta = Math.sin( theta );\r\n\t\t\t\t\tvar cosTheta = Math.cos( theta );\r\n\r\n\t\t\t\t\t// vertex\r\n\r\n\t\t\t\t\tvertex.x = radius * sinTheta;\r\n\t\t\t\t\tvertex.y = - v * height + halfHeight;\r\n\t\t\t\t\tvertex.z = radius * cosTheta;\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t// normal\r\n\r\n\t\t\t\t\tnormal.set( sinTheta, slope, cosTheta ).normalize();\r\n\t\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t\t// uv\r\n\r\n\t\t\t\t\tuvs.push( u, 1 - v );\r\n\r\n\t\t\t\t\t// save index of vertex in respective row\r\n\r\n\t\t\t\t\tindexRow.push( index ++ );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// now save vertices of the row in our index array\r\n\r\n\t\t\t\tindexArray.push( indexRow );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate indices\r\n\r\n\t\t\tfor ( x = 0; x < radialSegments; x ++ ) {\r\n\r\n\t\t\t\tfor ( y = 0; y < heightSegments; y ++ ) {\r\n\r\n\t\t\t\t\t// we use the index array to access the correct indices\r\n\r\n\t\t\t\t\tvar a = indexArray[ y ][ x ];\r\n\t\t\t\t\tvar b = indexArray[ y + 1 ][ x ];\r\n\t\t\t\t\tvar c = indexArray[ y + 1 ][ x + 1 ];\r\n\t\t\t\t\tvar d = indexArray[ y ][ x + 1 ];\r\n\r\n\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t\t// update group counter\r\n\r\n\t\t\t\t\tgroupCount += 6;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\tscope.addGroup( groupStart, groupCount, 0 );\r\n\r\n\t\t\t// calculate new start value for groups\r\n\r\n\t\t\tgroupStart += groupCount;\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateCap( top ) {\r\n\r\n\t\t\tvar x, centerIndexStart, centerIndexEnd;\r\n\r\n\t\t\tvar uv = new Vector2();\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tvar groupCount = 0;\r\n\r\n\t\t\tvar radius = ( top === true ) ? radiusTop : radiusBottom;\r\n\t\t\tvar sign = ( top === true ) ? 1 : - 1;\r\n\r\n\t\t\t// save the index of the first center vertex\r\n\t\t\tcenterIndexStart = index;\r\n\r\n\t\t\t// first we generate the center vertex data of the cap.\r\n\t\t\t// because the geometry needs one set of uvs per face,\r\n\t\t\t// we must generate a center vertex per face/segment\r\n\r\n\t\t\tfor ( x = 1; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertices.push( 0, halfHeight * sign, 0 );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, sign, 0 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( 0.5, 0.5 );\r\n\r\n\t\t\t\t// increase index\r\n\r\n\t\t\t\tindex ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// save the index of the last center vertex\r\n\r\n\t\t\tcenterIndexEnd = index;\r\n\r\n\t\t\t// now we generate the surrounding vertices, normals and uvs\r\n\r\n\t\t\tfor ( x = 0; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\tvar u = x / radialSegments;\r\n\t\t\t\tvar theta = u * thetaLength + thetaStart;\r\n\r\n\t\t\t\tvar cosTheta = Math.cos( theta );\r\n\t\t\t\tvar sinTheta = Math.sin( theta );\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = radius * sinTheta;\r\n\t\t\t\tvertex.y = halfHeight * sign;\r\n\t\t\t\tvertex.z = radius * cosTheta;\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, sign, 0 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = ( cosTheta * 0.5 ) + 0.5;\r\n\t\t\t\tuv.y = ( sinTheta * 0.5 * sign ) + 0.5;\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\t// increase index\r\n\r\n\t\t\t\tindex ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate indices\r\n\r\n\t\t\tfor ( x = 0; x < radialSegments; x ++ ) {\r\n\r\n\t\t\t\tvar c = centerIndexStart + x;\r\n\t\t\t\tvar i = centerIndexEnd + x;\r\n\r\n\t\t\t\tif ( top === true ) {\r\n\r\n\t\t\t\t\t// face top\r\n\r\n\t\t\t\t\tindices.push( i, i + 1, c );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// face bottom\r\n\r\n\t\t\t\t\tindices.push( i + 1, i, c );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgroupCount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\tscope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );\r\n\r\n\t\t\t// calculate new start value for groups\r\n\r\n\t\t\tgroupStart += groupCount;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tCylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tCylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t */\r\n\r\n\t// ConeGeometry\r\n\r\n\tfunction ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tCylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );\r\n\r\n\t\tthis.type = 'ConeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tConeGeometry.prototype = Object.create( CylinderGeometry.prototype );\r\n\tConeGeometry.prototype.constructor = ConeGeometry;\r\n\r\n\t// ConeBufferGeometry\r\n\r\n\tfunction ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tCylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );\r\n\r\n\t\tthis.type = 'ConeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );\r\n\tConeBufferGeometry.prototype.constructor = ConeBufferGeometry;\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author hughes\r\n\t */\r\n\r\n\t// CircleGeometry\r\n\r\n\tfunction CircleGeometry( radius, segments, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'CircleGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tsegments: segments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tCircleGeometry.prototype = Object.create( Geometry.prototype );\r\n\tCircleGeometry.prototype.constructor = CircleGeometry;\r\n\r\n\t// CircleBufferGeometry\r\n\r\n\tfunction CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'CircleBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tsegments: segments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\tsegments = segments !== undefined ? Math.max( 3, segments ) : 8;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, s;\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\r\n\t\t// center point\r\n\r\n\t\tvertices.push( 0, 0, 0 );\r\n\t\tnormals.push( 0, 0, 1 );\r\n\t\tuvs.push( 0.5, 0.5 );\r\n\r\n\t\tfor ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {\r\n\r\n\t\t\tvar segment = thetaStart + s / segments * thetaLength;\r\n\r\n\t\t\t// vertex\r\n\r\n\t\t\tvertex.x = radius * Math.cos( segment );\r\n\t\t\tvertex.y = radius * Math.sin( segment );\r\n\r\n\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t// normal\r\n\r\n\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t// uvs\r\n\r\n\t\t\tuv.x = ( vertices[ i ] / radius + 1 ) / 2;\r\n\t\t\tuv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;\r\n\r\n\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\tindices.push( i, i + 1, 0 );\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tCircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tCircleBufferGeometry.prototype.constructor = CircleBufferGeometry;\n\n\n\n\tvar Geometries = /*#__PURE__*/Object.freeze({\n\t\tWireframeGeometry: WireframeGeometry,\n\t\tParametricGeometry: ParametricGeometry,\n\t\tParametricBufferGeometry: ParametricBufferGeometry,\n\t\tTetrahedronGeometry: TetrahedronGeometry,\n\t\tTetrahedronBufferGeometry: TetrahedronBufferGeometry,\n\t\tOctahedronGeometry: OctahedronGeometry,\n\t\tOctahedronBufferGeometry: OctahedronBufferGeometry,\n\t\tIcosahedronGeometry: IcosahedronGeometry,\n\t\tIcosahedronBufferGeometry: IcosahedronBufferGeometry,\n\t\tDodecahedronGeometry: DodecahedronGeometry,\n\t\tDodecahedronBufferGeometry: DodecahedronBufferGeometry,\n\t\tPolyhedronGeometry: PolyhedronGeometry,\n\t\tPolyhedronBufferGeometry: PolyhedronBufferGeometry,\n\t\tTubeGeometry: TubeGeometry,\n\t\tTubeBufferGeometry: TubeBufferGeometry,\n\t\tTorusKnotGeometry: TorusKnotGeometry,\n\t\tTorusKnotBufferGeometry: TorusKnotBufferGeometry,\n\t\tTorusGeometry: TorusGeometry,\n\t\tTorusBufferGeometry: TorusBufferGeometry,\n\t\tTextGeometry: TextGeometry,\n\t\tTextBufferGeometry: TextBufferGeometry,\n\t\tSphereGeometry: SphereGeometry,\n\t\tSphereBufferGeometry: SphereBufferGeometry,\n\t\tRingGeometry: RingGeometry,\n\t\tRingBufferGeometry: RingBufferGeometry,\n\t\tPlaneGeometry: PlaneGeometry,\n\t\tPlaneBufferGeometry: PlaneBufferGeometry,\n\t\tLatheGeometry: LatheGeometry,\n\t\tLatheBufferGeometry: LatheBufferGeometry,\n\t\tShapeGeometry: ShapeGeometry,\n\t\tShapeBufferGeometry: ShapeBufferGeometry,\n\t\tExtrudeGeometry: ExtrudeGeometry,\n\t\tExtrudeBufferGeometry: ExtrudeBufferGeometry,\n\t\tEdgesGeometry: EdgesGeometry,\n\t\tConeGeometry: ConeGeometry,\n\t\tConeBufferGeometry: ConeBufferGeometry,\n\t\tCylinderGeometry: CylinderGeometry,\n\t\tCylinderBufferGeometry: CylinderBufferGeometry,\n\t\tCircleGeometry: CircleGeometry,\n\t\tCircleBufferGeometry: CircleBufferGeometry,\n\t\tBoxGeometry: BoxGeometry,\n\t\tBoxBufferGeometry: BoxBufferGeometry\n\t});\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: \r\n\t * }\r\n\t */\r\n\r\n\tfunction ShadowMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'ShadowMaterial';\r\n\r\n\t\tthis.color = new Color( 0x000000 );\r\n\t\tthis.transparent = true;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tShadowMaterial.prototype = Object.create( Material.prototype );\r\n\tShadowMaterial.prototype.constructor = ShadowMaterial;\r\n\r\n\tShadowMaterial.prototype.isShadowMaterial = true;\r\n\r\n\tShadowMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction RawShaderMaterial( parameters ) {\r\n\r\n\t\tShaderMaterial.call( this, parameters );\r\n\r\n\t\tthis.type = 'RawShaderMaterial';\r\n\r\n\t}\r\n\r\n\tRawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );\r\n\tRawShaderMaterial.prototype.constructor = RawShaderMaterial;\r\n\r\n\tRawShaderMaterial.prototype.isRawShaderMaterial = true;\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * roughness: ,\r\n\t * metalness: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * roughnessMap: new THREE.Texture( ),\r\n\t *\r\n\t * metalnessMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * envMapIntensity: \r\n\t *\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshStandardMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'STANDARD': '' };\r\n\r\n\t\tthis.type = 'MeshStandardMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\t\tthis.roughness = 0.5;\r\n\t\tthis.metalness = 0.5;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.roughnessMap = null;\r\n\r\n\t\tthis.metalnessMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.envMapIntensity = 1.0;\r\n\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshStandardMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshStandardMaterial.prototype.constructor = MeshStandardMaterial;\r\n\r\n\tMeshStandardMaterial.prototype.isMeshStandardMaterial = true;\r\n\r\n\tMeshStandardMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = { 'STANDARD': '' };\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.roughness = source.roughness;\r\n\t\tthis.metalness = source.metalness;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.roughnessMap = source.roughnessMap;\r\n\r\n\t\tthis.metalnessMap = source.metalnessMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.envMapIntensity = source.envMapIntensity;\r\n\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * reflectivity: \r\n\t * clearcoat: \r\n\t * clearcoatRoughness: \r\n\t *\r\n\t * sheen: \r\n\t *\r\n\t * clearcoatNormalScale: ,\r\n\t * clearcoatNormalMap: new THREE.Texture( ),\r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshPhysicalMaterial( parameters ) {\r\n\r\n\t\tMeshStandardMaterial.call( this );\r\n\r\n\t\tthis.defines = {\r\n\r\n\t\t\t'STANDARD': '',\r\n\t\t\t'PHYSICAL': ''\r\n\r\n\t\t};\r\n\r\n\t\tthis.type = 'MeshPhysicalMaterial';\r\n\r\n\t\tthis.reflectivity = 0.5; // maps to F0 = 0.04\r\n\r\n\t\tthis.clearcoat = 0.0;\r\n\t\tthis.clearcoatRoughness = 0.0;\r\n\r\n\t\tthis.sheen = null; // null will disable sheen bsdf\r\n\r\n\t\tthis.clearcoatNormalScale = new Vector2( 1, 1 );\r\n\t\tthis.clearcoatNormalMap = null;\r\n\r\n\t\tthis.transparency = 0.0;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );\r\n\tMeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;\r\n\r\n\tMeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;\r\n\r\n\tMeshPhysicalMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMeshStandardMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = {\r\n\r\n\t\t\t'STANDARD': '',\r\n\t\t\t'PHYSICAL': ''\r\n\r\n\t\t};\r\n\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\r\n\t\tthis.clearcoat = source.clearcoat;\r\n\t\tthis.clearcoatRoughness = source.clearcoatRoughness;\r\n\r\n\t\tif ( source.sheen ) { this.sheen = ( this.sheen || new Color() ).copy( source.sheen ); }\r\n\t\telse { this.sheen = null; }\r\n\r\n\t\tthis.clearcoatNormalMap = source.clearcoatNormalMap;\r\n\t\tthis.clearcoatNormalScale.copy( source.clearcoatNormalScale );\r\n\r\n\t\tthis.transparency = source.transparency;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * specular: ,\r\n\t * shininess: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.MultiplyOperation,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshPhongMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshPhongMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\t\tthis.specular = new Color( 0x111111 );\r\n\t\tthis.shininess = 30;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshPhongMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshPhongMaterial.prototype.constructor = MeshPhongMaterial;\r\n\r\n\tMeshPhongMaterial.prototype.isMeshPhongMaterial = true;\r\n\r\n\tMeshPhongMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.specular.copy( source.specular );\r\n\t\tthis.shininess = source.shininess;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author takahirox / http://github.com/takahirox\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * specular: ,\r\n\t * shininess: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t * gradientMap: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshToonMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'TOON': '' };\r\n\r\n\t\tthis.type = 'MeshToonMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\t\tthis.specular = new Color( 0x111111 );\r\n\t\tthis.shininess = 30;\r\n\r\n\t\tthis.map = null;\r\n\t\tthis.gradientMap = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshToonMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshToonMaterial.prototype.constructor = MeshToonMaterial;\r\n\r\n\tMeshToonMaterial.prototype.isMeshToonMaterial = true;\r\n\r\n\tMeshToonMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.specular.copy( source.specular );\r\n\t\tthis.shininess = source.shininess;\r\n\r\n\t\tthis.map = source.map;\r\n\t\tthis.gradientMap = source.gradientMap;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * opacity: ,\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: \r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshNormalMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshNormalMaterial';\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshNormalMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshNormalMaterial.prototype.constructor = MeshNormalMaterial;\r\n\r\n\tMeshNormalMaterial.prototype.isMeshNormalMaterial = true;\r\n\r\n\tMeshNormalMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.Multiply,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshLambertMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshLambertMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshLambertMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshLambertMaterial.prototype.constructor = MeshLambertMaterial;\r\n\r\n\tMeshLambertMaterial.prototype.isMeshLambertMaterial = true;\r\n\r\n\tMeshLambertMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * matcap: new THREE.Texture( ),\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshMatcapMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'MATCAP': '' };\r\n\r\n\t\tthis.type = 'MeshMatcapMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\r\n\t\tthis.matcap = null;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshMatcapMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;\r\n\r\n\tMeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;\r\n\r\n\tMeshMatcapMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = { 'MATCAP': '' };\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.matcap = source.matcap;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * linewidth: ,\r\n\t *\r\n\t * scale: ,\r\n\t * dashSize: ,\r\n\t * gapSize: \r\n\t * }\r\n\t */\r\n\r\n\tfunction LineDashedMaterial( parameters ) {\r\n\r\n\t\tLineBasicMaterial.call( this );\r\n\r\n\t\tthis.type = 'LineDashedMaterial';\r\n\r\n\t\tthis.scale = 1;\r\n\t\tthis.dashSize = 3;\r\n\t\tthis.gapSize = 1;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tLineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );\r\n\tLineDashedMaterial.prototype.constructor = LineDashedMaterial;\r\n\r\n\tLineDashedMaterial.prototype.isLineDashedMaterial = true;\r\n\r\n\tLineDashedMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tLineBasicMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.scale = source.scale;\r\n\t\tthis.dashSize = source.dashSize;\r\n\t\tthis.gapSize = source.gapSize;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\n\n\tvar Materials = /*#__PURE__*/Object.freeze({\n\t\tShadowMaterial: ShadowMaterial,\n\t\tSpriteMaterial: SpriteMaterial,\n\t\tRawShaderMaterial: RawShaderMaterial,\n\t\tShaderMaterial: ShaderMaterial,\n\t\tPointsMaterial: PointsMaterial,\n\t\tMeshPhysicalMaterial: MeshPhysicalMaterial,\n\t\tMeshStandardMaterial: MeshStandardMaterial,\n\t\tMeshPhongMaterial: MeshPhongMaterial,\n\t\tMeshToonMaterial: MeshToonMaterial,\n\t\tMeshNormalMaterial: MeshNormalMaterial,\n\t\tMeshLambertMaterial: MeshLambertMaterial,\n\t\tMeshDepthMaterial: MeshDepthMaterial,\n\t\tMeshDistanceMaterial: MeshDistanceMaterial,\n\t\tMeshBasicMaterial: MeshBasicMaterial,\n\t\tMeshMatcapMaterial: MeshMatcapMaterial,\n\t\tLineDashedMaterial: LineDashedMaterial,\n\t\tLineBasicMaterial: LineBasicMaterial,\n\t\tMaterial: Material\n\t});\n\n\t/**\r\n\t * @author tschw\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t */\r\n\r\n\tvar AnimationUtils = {\r\n\r\n\t\t// same as Array.prototype.slice, but also works on typed arrays\r\n\t\tarraySlice: function ( array, from, to ) {\r\n\r\n\t\t\tif ( AnimationUtils.isTypedArray( array ) ) {\r\n\r\n\t\t\t\t// in ios9 array.subarray(from, undefined) will return empty array\r\n\t\t\t\t// but array.subarray(from) or array.subarray(from, len) is correct\r\n\t\t\t\treturn new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn array.slice( from, to );\r\n\r\n\t\t},\r\n\r\n\t\t// converts an array to a specific type\r\n\t\tconvertArray: function ( array, type, forceClone ) {\r\n\r\n\t\t\tif ( ! array || // let 'undefined' and 'null' pass\r\n\t\t\t\t! forceClone && array.constructor === type ) { return array; }\r\n\r\n\t\t\tif ( typeof type.BYTES_PER_ELEMENT === 'number' ) {\r\n\r\n\t\t\t\treturn new type( array ); // create typed array\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn Array.prototype.slice.call( array ); // create Array\r\n\r\n\t\t},\r\n\r\n\t\tisTypedArray: function ( object ) {\r\n\r\n\t\t\treturn ArrayBuffer.isView( object ) &&\r\n\t\t\t\t! ( object instanceof DataView );\r\n\r\n\t\t},\r\n\r\n\t\t// returns an array by which times and values can be sorted\r\n\t\tgetKeyframeOrder: function ( times ) {\r\n\r\n\t\t\tfunction compareTime( i, j ) {\r\n\r\n\t\t\t\treturn times[ i ] - times[ j ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar n = times.length;\r\n\t\t\tvar result = new Array( n );\r\n\t\t\tfor ( var i = 0; i !== n; ++ i ) { result[ i ] = i; }\r\n\r\n\t\t\tresult.sort( compareTime );\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// uses the array previously returned by 'getKeyframeOrder' to sort data\r\n\t\tsortedArray: function ( values, stride, order ) {\r\n\r\n\t\t\tvar nValues = values.length;\r\n\t\t\tvar result = new values.constructor( nValues );\r\n\r\n\t\t\tfor ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {\r\n\r\n\t\t\t\tvar srcOffset = order[ i ] * stride;\r\n\r\n\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\tresult[ dstOffset ++ ] = values[ srcOffset + j ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// function for parsing AOS keyframe formats\r\n\t\tflattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {\r\n\r\n\t\t\tvar i = 1, key = jsonKeys[ 0 ];\r\n\r\n\t\t\twhile ( key !== undefined && key[ valuePropertyName ] === undefined ) {\r\n\r\n\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( key === undefined ) { return; } // no data\r\n\r\n\t\t\tvar value = key[ valuePropertyName ];\r\n\t\t\tif ( value === undefined ) { return; } // no data\r\n\r\n\t\t\tif ( Array.isArray( value ) ) {\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalues.push.apply( values, value ); // push all elements\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t} else if ( value.toArray !== undefined ) {\r\n\r\n\t\t\t\t// ...assume THREE.Math-ish\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalue.toArray( values, values.length );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// otherwise push as-is\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalues.push( value );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tsubclip: function ( sourceClip, name, startFrame, endFrame, fps ) {\r\n\r\n\t\t\tfps = fps || 30;\r\n\r\n\t\t\tvar clip = sourceClip.clone();\r\n\r\n\t\t\tclip.name = name;\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tvar track = clip.tracks[ i ];\r\n\t\t\t\tvar valueSize = track.getValueSize();\r\n\r\n\t\t\t\tvar times = [];\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\tfor ( var j = 0; j < track.times.length; ++ j ) {\r\n\r\n\t\t\t\t\tvar frame = track.times[ j ] * fps;\r\n\r\n\t\t\t\t\tif ( frame < startFrame || frame >= endFrame ) { continue; }\r\n\r\n\t\t\t\t\ttimes.push( track.times[ j ] );\r\n\r\n\t\t\t\t\tfor ( var k = 0; k < valueSize; ++ k ) {\r\n\r\n\t\t\t\t\t\tvalues.push( track.values[ j * valueSize + k ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( times.length === 0 ) { continue; }\r\n\r\n\t\t\t\ttrack.times = AnimationUtils.convertArray( times, track.times.constructor );\r\n\t\t\t\ttrack.values = AnimationUtils.convertArray( values, track.values.constructor );\r\n\r\n\t\t\t\ttracks.push( track );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tclip.tracks = tracks;\r\n\r\n\t\t\t// find minimum .times value across all tracks in the trimmed clip\r\n\r\n\t\t\tvar minStartTime = Infinity;\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tif ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {\r\n\r\n\t\t\t\t\tminStartTime = clip.tracks[ i ].times[ 0 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// shift all tracks such that clip begins at t=0\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tclip.tracks[ i ].shift( - 1 * minStartTime );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tclip.resetDuration();\r\n\r\n\t\t\treturn clip;\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * Abstract base class of interpolants over parametric samples.\r\n\t *\r\n\t * The parameter domain is one dimensional, typically the time or a path\r\n\t * along a curve defined by the data.\r\n\t *\r\n\t * The sample values can have any dimensionality and derived classes may\r\n\t * apply special interpretations to the data.\r\n\t *\r\n\t * This class provides the interval seek in a Template Method, deferring\r\n\t * the actual interpolation to derived classes.\r\n\t *\r\n\t * Time complexity is O(1) for linear access crossing at most two points\r\n\t * and O(log N) for random access, where N is the number of positions.\r\n\t *\r\n\t * References:\r\n\t *\r\n\t * \t\thttp://www.oodesign.com/template-method-pattern.html\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tthis.parameterPositions = parameterPositions;\r\n\t\tthis._cachedIndex = 0;\r\n\r\n\t\tthis.resultBuffer = resultBuffer !== undefined ?\r\n\t\t\tresultBuffer : new sampleValues.constructor( sampleSize );\r\n\t\tthis.sampleValues = sampleValues;\r\n\t\tthis.valueSize = sampleSize;\r\n\r\n\t}\r\n\r\n\tObject.assign( Interpolant.prototype, {\r\n\r\n\t\tevaluate: function ( t ) {\r\n\r\n\t\t\tvar pp = this.parameterPositions,\r\n\t\t\t\ti1 = this._cachedIndex,\r\n\r\n\t\t\t\tt1 = pp[ i1 ],\r\n\t\t\t\tt0 = pp[ i1 - 1 ];\r\n\r\n\t\t\tvalidate_interval: {\r\n\r\n\t\t\t\tseek: {\r\n\r\n\t\t\t\t\tvar right;\r\n\r\n\t\t\t\t\tlinear_scan: {\r\n\r\n\t\t\t\t\t\t//- See http://jsperf.com/comparison-to-undefined/3\r\n\t\t\t\t\t\t//- slower code:\r\n\t\t\t\t\t\t//-\r\n\t\t\t\t\t\t//- \t\t\t\tif ( t >= t1 || t1 === undefined ) {\r\n\t\t\t\t\t\tforward_scan: if ( ! ( t < t1 ) ) {\r\n\r\n\t\t\t\t\t\t\tfor ( var giveUpAt = i1 + 2; ; ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( t1 === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tif ( t < t0 ) { break forward_scan; }\r\n\r\n\t\t\t\t\t\t\t\t\t// after end\r\n\r\n\t\t\t\t\t\t\t\t\ti1 = pp.length;\r\n\t\t\t\t\t\t\t\t\tthis._cachedIndex = i1;\r\n\t\t\t\t\t\t\t\t\treturn this.afterEnd_( i1 - 1, t, t0 );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tif ( i1 === giveUpAt ) { break; } // this loop\r\n\r\n\t\t\t\t\t\t\t\tt0 = t1;\r\n\t\t\t\t\t\t\t\tt1 = pp[ ++ i1 ];\r\n\r\n\t\t\t\t\t\t\t\tif ( t < t1 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// we have arrived at the sought interval\r\n\t\t\t\t\t\t\t\t\tbreak seek;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// prepare binary search on the right side of the index\r\n\t\t\t\t\t\t\tright = pp.length;\r\n\t\t\t\t\t\t\tbreak linear_scan;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t//- slower code:\r\n\t\t\t\t\t\t//-\t\t\t\t\tif ( t < t0 || t0 === undefined ) {\r\n\t\t\t\t\t\tif ( ! ( t >= t0 ) ) {\r\n\r\n\t\t\t\t\t\t\t// looping?\r\n\r\n\t\t\t\t\t\t\tvar t1global = pp[ 1 ];\r\n\r\n\t\t\t\t\t\t\tif ( t < t1global ) {\r\n\r\n\t\t\t\t\t\t\t\ti1 = 2; // + 1, using the scan for the details\r\n\t\t\t\t\t\t\t\tt0 = t1global;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// linear reverse scan\r\n\r\n\t\t\t\t\t\t\tfor ( var giveUpAt = i1 - 2; ; ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( t0 === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// before start\r\n\r\n\t\t\t\t\t\t\t\t\tthis._cachedIndex = 0;\r\n\t\t\t\t\t\t\t\t\treturn this.beforeStart_( 0, t, t1 );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tif ( i1 === giveUpAt ) { break; } // this loop\r\n\r\n\t\t\t\t\t\t\t\tt1 = t0;\r\n\t\t\t\t\t\t\t\tt0 = pp[ -- i1 - 1 ];\r\n\r\n\t\t\t\t\t\t\t\tif ( t >= t0 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// we have arrived at the sought interval\r\n\t\t\t\t\t\t\t\t\tbreak seek;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// prepare binary search on the left side of the index\r\n\t\t\t\t\t\t\tright = i1;\r\n\t\t\t\t\t\t\ti1 = 0;\r\n\t\t\t\t\t\t\tbreak linear_scan;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// the interval is valid\r\n\r\n\t\t\t\t\t\tbreak validate_interval;\r\n\r\n\t\t\t\t\t} // linear scan\r\n\r\n\t\t\t\t\t// binary search\r\n\r\n\t\t\t\t\twhile ( i1 < right ) {\r\n\r\n\t\t\t\t\t\tvar mid = ( i1 + right ) >>> 1;\r\n\r\n\t\t\t\t\t\tif ( t < pp[ mid ] ) {\r\n\r\n\t\t\t\t\t\t\tright = mid;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\ti1 = mid + 1;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tt1 = pp[ i1 ];\r\n\t\t\t\t\tt0 = pp[ i1 - 1 ];\r\n\r\n\t\t\t\t\t// check boundary cases, again\r\n\r\n\t\t\t\t\tif ( t0 === undefined ) {\r\n\r\n\t\t\t\t\t\tthis._cachedIndex = 0;\r\n\t\t\t\t\t\treturn this.beforeStart_( 0, t, t1 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( t1 === undefined ) {\r\n\r\n\t\t\t\t\t\ti1 = pp.length;\r\n\t\t\t\t\t\tthis._cachedIndex = i1;\r\n\t\t\t\t\t\treturn this.afterEnd_( i1 - 1, t0, t );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} // seek\r\n\r\n\t\t\t\tthis._cachedIndex = i1;\r\n\r\n\t\t\t\tthis.intervalChanged_( i1, t0, t1 );\r\n\r\n\t\t\t} // validate_interval\r\n\r\n\t\t\treturn this.interpolate_( i1, t0, t, t1 );\r\n\r\n\t\t},\r\n\r\n\t\tsettings: null, // optional, subclass-specific settings structure\r\n\t\t// Note: The indirection allows central control of many interpolants.\r\n\r\n\t\t// --- Protected interface\r\n\r\n\t\tDefaultSettings_: {},\r\n\r\n\t\tgetSettings_: function () {\r\n\r\n\t\t\treturn this.settings || this.DefaultSettings_;\r\n\r\n\t\t},\r\n\r\n\t\tcopySampleValue_: function ( index ) {\r\n\r\n\t\t\t// copies a sample value to the result buffer\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\t\t\t\toffset = index * stride;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] = values[ offset + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// Template methods for derived classes:\r\n\r\n\t\tinterpolate_: function ( /* i1, t0, t, t1 */ ) {\r\n\r\n\t\t\tthrow new Error( 'call to abstract method' );\r\n\t\t\t// implementations shall return this.resultBuffer\r\n\r\n\t\t},\r\n\r\n\t\tintervalChanged_: function ( /* i1, t0, t1 */ ) {\r\n\r\n\t\t\t// empty\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//!\\ DECLARE ALIAS AFTER assign prototype !\r\n\tObject.assign( Interpolant.prototype, {\r\n\r\n\t\t//( 0, t, t0 ), returns this.resultBuffer\r\n\t\tbeforeStart_: Interpolant.prototype.copySampleValue_,\r\n\r\n\t\t//( N-1, tN-1, t ), returns this.resultBuffer\r\n\t\tafterEnd_: Interpolant.prototype.copySampleValue_,\r\n\r\n\t} );\n\n\t/**\r\n\t * Fast and simple cubic spline interpolant.\r\n\t *\r\n\t * It was derived from a Hermitian construction setting the first derivative\r\n\t * at each sample position to the linear slope between neighboring positions\r\n\t * over their parameter interval.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t\tthis._weightPrev = - 0;\r\n\t\tthis._offsetPrev = - 0;\r\n\t\tthis._weightNext = - 0;\r\n\t\tthis._offsetNext = - 0;\r\n\r\n\t}\r\n\r\n\tCubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: CubicInterpolant,\r\n\r\n\t\tDefaultSettings_: {\r\n\r\n\t\t\tendingStart: ZeroCurvatureEnding,\r\n\t\t\tendingEnd: ZeroCurvatureEnding\r\n\r\n\t\t},\r\n\r\n\t\tintervalChanged_: function ( i1, t0, t1 ) {\r\n\r\n\t\t\tvar pp = this.parameterPositions,\r\n\t\t\t\tiPrev = i1 - 2,\r\n\t\t\t\tiNext = i1 + 1,\r\n\r\n\t\t\t\ttPrev = pp[ iPrev ],\r\n\t\t\t\ttNext = pp[ iNext ];\r\n\r\n\t\t\tif ( tPrev === undefined ) {\r\n\r\n\t\t\t\tswitch ( this.getSettings_().endingStart ) {\r\n\r\n\t\t\t\t\tcase ZeroSlopeEnding:\r\n\r\n\t\t\t\t\t\t// f'(t0) = 0\r\n\t\t\t\t\t\tiPrev = i1;\r\n\t\t\t\t\t\ttPrev = 2 * t0 - t1;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase WrapAroundEnding:\r\n\r\n\t\t\t\t\t\t// use the other end of the curve\r\n\t\t\t\t\t\tiPrev = pp.length - 2;\r\n\t\t\t\t\t\ttPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault: // ZeroCurvatureEnding\r\n\r\n\t\t\t\t\t\t// f''(t0) = 0 a.k.a. Natural Spline\r\n\t\t\t\t\t\tiPrev = i1;\r\n\t\t\t\t\t\ttPrev = t1;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tNext === undefined ) {\r\n\r\n\t\t\t\tswitch ( this.getSettings_().endingEnd ) {\r\n\r\n\t\t\t\t\tcase ZeroSlopeEnding:\r\n\r\n\t\t\t\t\t\t// f'(tN) = 0\r\n\t\t\t\t\t\tiNext = i1;\r\n\t\t\t\t\t\ttNext = 2 * t1 - t0;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase WrapAroundEnding:\r\n\r\n\t\t\t\t\t\t// use the other end of the curve\r\n\t\t\t\t\t\tiNext = 1;\r\n\t\t\t\t\t\ttNext = t1 + pp[ 1 ] - pp[ 0 ];\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault: // ZeroCurvatureEnding\r\n\r\n\t\t\t\t\t\t// f''(tN) = 0, a.k.a. Natural Spline\r\n\t\t\t\t\t\tiNext = i1 - 1;\r\n\t\t\t\t\t\ttNext = t0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar halfDt = ( t1 - t0 ) * 0.5,\r\n\t\t\t\tstride = this.valueSize;\r\n\r\n\t\t\tthis._weightPrev = halfDt / ( t0 - tPrev );\r\n\t\t\tthis._weightNext = halfDt / ( tNext - t1 );\r\n\t\t\tthis._offsetPrev = iPrev * stride;\r\n\t\t\tthis._offsetNext = iNext * stride;\r\n\r\n\t\t},\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\to1 = i1 * stride,\t\to0 = o1 - stride,\r\n\t\t\t\toP = this._offsetPrev, \toN = this._offsetNext,\r\n\t\t\t\twP = this._weightPrev,\twN = this._weightNext,\r\n\r\n\t\t\t\tp = ( t - t0 ) / ( t1 - t0 ),\r\n\t\t\t\tpp = p * p,\r\n\t\t\t\tppp = pp * p;\r\n\r\n\t\t\t// evaluate polynomials\r\n\r\n\t\t\tvar sP = - wP * ppp + 2 * wP * pp - wP * p;\r\n\t\t\tvar s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;\r\n\t\t\tvar s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;\r\n\t\t\tvar sN = wN * ppp - wN * pp;\r\n\r\n\t\t\t// combine data linearly\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] =\r\n\t\t\t\t\t\tsP * values[ oP + i ] +\r\n\t\t\t\t\t\ts0 * values[ o0 + i ] +\r\n\t\t\t\t\t\ts1 * values[ o1 + i ] +\r\n\t\t\t\t\t\tsN * values[ oN + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: LinearInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toffset1 = i1 * stride,\r\n\t\t\t\toffset0 = offset1 - stride,\r\n\r\n\t\t\t\tweight1 = ( t - t0 ) / ( t1 - t0 ),\r\n\t\t\t\tweight0 = 1 - weight1;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] =\r\n\t\t\t\t\t\tvalues[ offset0 + i ] * weight0 +\r\n\t\t\t\t\t\tvalues[ offset1 + i ] * weight1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Interpolant that evaluates to the sample value at the position preceeding\r\n\t * the parameter.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tDiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: DiscreteInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1 /*, t0, t, t1 */ ) {\r\n\r\n\t\t\treturn this.copySampleValue_( i1 - 1 );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A timed sequence of keyframes for a specific property.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction KeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tif ( name === undefined ) { throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); }\r\n\t\tif ( times === undefined || times.length === 0 ) { throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); }\r\n\r\n\t\tthis.name = name;\r\n\r\n\t\tthis.times = AnimationUtils.convertArray( times, this.TimeBufferType );\r\n\t\tthis.values = AnimationUtils.convertArray( values, this.ValueBufferType );\r\n\r\n\t\tthis.setInterpolation( interpolation || this.DefaultInterpolation );\r\n\r\n\t}\r\n\r\n\t// Static methods\r\n\r\n\tObject.assign( KeyframeTrack, {\r\n\r\n\t\t// Serialization (in static context, because of constructor invocation\r\n\t\t// and automatic invocation of .toJSON):\r\n\r\n\t\ttoJSON: function ( track ) {\r\n\r\n\t\t\tvar trackType = track.constructor;\r\n\r\n\t\t\tvar json;\r\n\r\n\t\t\t// derived classes can define a static toJSON method\r\n\t\t\tif ( trackType.toJSON !== undefined ) {\r\n\r\n\t\t\t\tjson = trackType.toJSON( track );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// by default, we assume the data can be serialized as-is\r\n\t\t\t\tjson = {\r\n\r\n\t\t\t\t\t'name': track.name,\r\n\t\t\t\t\t'times': AnimationUtils.convertArray( track.times, Array ),\r\n\t\t\t\t\t'values': AnimationUtils.convertArray( track.values, Array )\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar interpolation = track.getInterpolation();\r\n\r\n\t\t\t\tif ( interpolation !== track.DefaultInterpolation ) {\r\n\r\n\t\t\t\t\tjson.interpolation = interpolation;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tjson.type = track.ValueTypeName; // mandatory\r\n\r\n\t\t\treturn json;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( KeyframeTrack.prototype, {\r\n\r\n\t\tconstructor: KeyframeTrack,\r\n\r\n\t\tTimeBufferType: Float32Array,\r\n\r\n\t\tValueBufferType: Float32Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateLinear,\r\n\r\n\t\tInterpolantFactoryMethodDiscrete: function ( result ) {\r\n\r\n\t\t\treturn new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodLinear: function ( result ) {\r\n\r\n\t\t\treturn new LinearInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodSmooth: function ( result ) {\r\n\r\n\t\t\treturn new CubicInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tsetInterpolation: function ( interpolation ) {\r\n\r\n\t\t\tvar factoryMethod;\r\n\r\n\t\t\tswitch ( interpolation ) {\r\n\r\n\t\t\t\tcase InterpolateDiscrete:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodDiscrete;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase InterpolateLinear:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodLinear;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase InterpolateSmooth:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodSmooth;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( factoryMethod === undefined ) {\r\n\r\n\t\t\t\tvar message = \"unsupported interpolation for \" +\r\n\t\t\t\t\tthis.ValueTypeName + \" keyframe track named \" + this.name;\r\n\r\n\t\t\t\tif ( this.createInterpolant === undefined ) {\r\n\r\n\t\t\t\t\t// fall back to default, unless the default itself is messed up\r\n\t\t\t\t\tif ( interpolation !== this.DefaultInterpolation ) {\r\n\r\n\t\t\t\t\t\tthis.setInterpolation( this.DefaultInterpolation );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthrow new Error( message ); // fatal, in this case\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconsole.warn( 'THREE.KeyframeTrack:', message );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.createInterpolant = factoryMethod;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetInterpolation: function () {\r\n\r\n\t\t\tswitch ( this.createInterpolant ) {\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodDiscrete:\r\n\r\n\t\t\t\t\treturn InterpolateDiscrete;\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodLinear:\r\n\r\n\t\t\t\t\treturn InterpolateLinear;\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodSmooth:\r\n\r\n\t\t\t\t\treturn InterpolateSmooth;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tgetValueSize: function () {\r\n\r\n\t\t\treturn this.values.length / this.times.length;\r\n\r\n\t\t},\r\n\r\n\t\t// move all keyframes either forwards or backwards in time\r\n\t\tshift: function ( timeOffset ) {\r\n\r\n\t\t\tif ( timeOffset !== 0.0 ) {\r\n\r\n\t\t\t\tvar times = this.times;\r\n\r\n\t\t\t\tfor ( var i = 0, n = times.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\ttimes[ i ] += timeOffset;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// scale all keyframe times by a factor (useful for frame <-> seconds conversions)\r\n\t\tscale: function ( timeScale ) {\r\n\r\n\t\t\tif ( timeScale !== 1.0 ) {\r\n\r\n\t\t\t\tvar times = this.times;\r\n\r\n\t\t\t\tfor ( var i = 0, n = times.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\ttimes[ i ] *= timeScale;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// removes keyframes before and after animation without changing any values within the range [startTime, endTime].\r\n\t\t// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values\r\n\t\ttrim: function ( startTime, endTime ) {\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tnKeys = times.length,\r\n\t\t\t\tfrom = 0,\r\n\t\t\t\tto = nKeys - 1;\r\n\r\n\t\t\twhile ( from !== nKeys && times[ from ] < startTime ) {\r\n\r\n\t\t\t\t++ from;\r\n\r\n\t\t\t}\r\n\r\n\t\t\twhile ( to !== - 1 && times[ to ] > endTime ) {\r\n\r\n\t\t\t\t-- to;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t++ to; // inclusive -> exclusive bound\r\n\r\n\t\t\tif ( from !== 0 || to !== nKeys ) {\r\n\r\n\t\t\t\t// empty tracks are forbidden, so keep at least one keyframe\r\n\t\t\t\tif ( from >= to ) { to = Math.max( to, 1 ), from = to - 1; }\r\n\r\n\t\t\t\tvar stride = this.getValueSize();\r\n\t\t\t\tthis.times = AnimationUtils.arraySlice( times, from, to );\r\n\t\t\t\tthis.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable\r\n\t\tvalidate: function () {\r\n\r\n\t\t\tvar valid = true;\r\n\r\n\t\t\tvar valueSize = this.getValueSize();\r\n\t\t\tif ( valueSize - Math.floor( valueSize ) !== 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );\r\n\t\t\t\tvalid = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tvalues = this.values,\r\n\r\n\t\t\t\tnKeys = times.length;\r\n\r\n\t\t\tif ( nKeys === 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Track is empty.', this );\r\n\t\t\t\tvalid = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar prevTime = null;\r\n\r\n\t\t\tfor ( var i = 0; i !== nKeys; i ++ ) {\r\n\r\n\t\t\t\tvar currTime = times[ i ];\r\n\r\n\t\t\t\tif ( typeof currTime === 'number' && isNaN( currTime ) ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );\r\n\t\t\t\t\tvalid = false;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( prevTime !== null && prevTime > currTime ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );\r\n\t\t\t\t\tvalid = false;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tprevTime = currTime;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( values !== undefined ) {\r\n\r\n\t\t\t\tif ( AnimationUtils.isTypedArray( values ) ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = values.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tvar value = values[ i ];\r\n\r\n\t\t\t\t\t\tif ( isNaN( value ) ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );\r\n\t\t\t\t\t\t\tvalid = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn valid;\r\n\r\n\t\t},\r\n\r\n\t\t// removes equivalent sequential keys as common in morph target sequences\r\n\t\t// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)\r\n\t\toptimize: function () {\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tvalues = this.values,\r\n\t\t\t\tstride = this.getValueSize(),\r\n\r\n\t\t\t\tsmoothInterpolation = this.getInterpolation() === InterpolateSmooth,\r\n\r\n\t\t\t\twriteIndex = 1,\r\n\t\t\t\tlastIndex = times.length - 1;\r\n\r\n\t\t\tfor ( var i = 1; i < lastIndex; ++ i ) {\r\n\r\n\t\t\t\tvar keep = false;\r\n\r\n\t\t\t\tvar time = times[ i ];\r\n\t\t\t\tvar timeNext = times[ i + 1 ];\r\n\r\n\t\t\t\t// remove adjacent keyframes scheduled at the same time\r\n\r\n\t\t\t\tif ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {\r\n\r\n\t\t\t\t\tif ( ! smoothInterpolation ) {\r\n\r\n\t\t\t\t\t\t// remove unnecessary keyframes same as their neighbors\r\n\r\n\t\t\t\t\t\tvar offset = i * stride,\r\n\t\t\t\t\t\t\toffsetP = offset - stride,\r\n\t\t\t\t\t\t\toffsetN = offset + stride;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar value = values[ offset + j ];\r\n\r\n\t\t\t\t\t\t\tif ( value !== values[ offsetP + j ] ||\r\n\t\t\t\t\t\t\t\tvalue !== values[ offsetN + j ] ) {\r\n\r\n\t\t\t\t\t\t\t\tkeep = true;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tkeep = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// in-place compaction\r\n\r\n\t\t\t\tif ( keep ) {\r\n\r\n\t\t\t\t\tif ( i !== writeIndex ) {\r\n\r\n\t\t\t\t\t\ttimes[ writeIndex ] = times[ i ];\r\n\r\n\t\t\t\t\t\tvar readOffset = i * stride,\r\n\t\t\t\t\t\t\twriteOffset = writeIndex * stride;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvalues[ writeOffset + j ] = values[ readOffset + j ];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t++ writeIndex;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// flush last keyframe (compaction looks ahead)\r\n\r\n\t\t\tif ( lastIndex > 0 ) {\r\n\r\n\t\t\t\ttimes[ writeIndex ] = times[ lastIndex ];\r\n\r\n\t\t\t\tfor ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\tvalues[ writeOffset + j ] = values[ readOffset + j ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t++ writeIndex;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( writeIndex !== times.length ) {\r\n\r\n\t\t\t\tthis.times = AnimationUtils.arraySlice( times, 0, writeIndex );\r\n\t\t\t\tthis.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\tvar times = AnimationUtils.arraySlice( this.times, 0 );\r\n\t\t\tvar values = AnimationUtils.arraySlice( this.values, 0 );\r\n\r\n\t\t\tvar TypedKeyframeTrack = this.constructor;\r\n\t\t\tvar track = new TypedKeyframeTrack( this.name, times, values );\r\n\r\n\t\t\t// Interpolant argument to constructor is not saved, so copy the factory method directly.\r\n\t\t\ttrack.createInterpolant = this.createInterpolant;\r\n\r\n\t\t\treturn track;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of Boolean keyframe values.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction BooleanKeyframeTrack( name, times, values ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values );\r\n\r\n\t}\r\n\r\n\tBooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: BooleanKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'bool',\r\n\t\tValueBufferType: Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateDiscrete,\r\n\r\n\t\tInterpolantFactoryMethodLinear: undefined,\r\n\t\tInterpolantFactoryMethodSmooth: undefined\r\n\r\n\t\t// Note: Actually this track could have a optimized / compressed\r\n\t\t// representation of a single value and a custom interpolant that\r\n\t\t// computes \"firstValue ^ isOdd( index )\".\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of keyframe values that represent color.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction ColorKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: ColorKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'color'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t\t// Note: Very basic implementation and nothing special yet.\r\n\t\t// However, this is the place for color space parameterization.\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of numeric keyframe values.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction NumberKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tNumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: NumberKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'number'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t} );\n\n\t/**\r\n\t * Spherical linear unit quaternion interpolant.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tQuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: QuaternionLinearInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toffset = i1 * stride,\r\n\r\n\t\t\t\talpha = ( t - t0 ) / ( t1 - t0 );\r\n\r\n\t\t\tfor ( var end = offset + stride; offset !== end; offset += 4 ) {\r\n\r\n\t\t\t\tQuaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of quaternion keyframe values.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction QuaternionKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tQuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: QuaternionKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'quaternion',\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\tDefaultInterpolation: InterpolateLinear,\r\n\r\n\t\tInterpolantFactoryMethodLinear: function ( result ) {\r\n\r\n\t\t\treturn new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodSmooth: undefined // not yet implemented\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track that interpolates Strings\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction StringKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tStringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: StringKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'string',\r\n\t\tValueBufferType: Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateDiscrete,\r\n\r\n\t\tInterpolantFactoryMethodLinear: undefined,\r\n\r\n\t\tInterpolantFactoryMethodSmooth: undefined\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of vectored keyframe values.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction VectorKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tVectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: VectorKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'vector'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Reusable set of Tracks that represent an animation.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t */\r\n\r\n\tfunction AnimationClip( name, duration, tracks ) {\r\n\r\n\t\tthis.name = name;\r\n\t\tthis.tracks = tracks;\r\n\t\tthis.duration = ( duration !== undefined ) ? duration : - 1;\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\t// this means it should figure out its duration by scanning the tracks\r\n\t\tif ( this.duration < 0 ) {\r\n\r\n\t\t\tthis.resetDuration();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction getTrackTypeForValueTypeName( typeName ) {\r\n\r\n\t\tswitch ( typeName.toLowerCase() ) {\r\n\r\n\t\t\tcase 'scalar':\r\n\t\t\tcase 'double':\r\n\t\t\tcase 'float':\r\n\t\t\tcase 'number':\r\n\t\t\tcase 'integer':\r\n\r\n\t\t\t\treturn NumberKeyframeTrack;\r\n\r\n\t\t\tcase 'vector':\r\n\t\t\tcase 'vector2':\r\n\t\t\tcase 'vector3':\r\n\t\t\tcase 'vector4':\r\n\r\n\t\t\t\treturn VectorKeyframeTrack;\r\n\r\n\t\t\tcase 'color':\r\n\r\n\t\t\t\treturn ColorKeyframeTrack;\r\n\r\n\t\t\tcase 'quaternion':\r\n\r\n\t\t\t\treturn QuaternionKeyframeTrack;\r\n\r\n\t\t\tcase 'bool':\r\n\t\t\tcase 'boolean':\r\n\r\n\t\t\t\treturn BooleanKeyframeTrack;\r\n\r\n\t\t\tcase 'string':\r\n\r\n\t\t\t\treturn StringKeyframeTrack;\r\n\r\n\t\t}\r\n\r\n\t\tthrow new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );\r\n\r\n\t}\r\n\r\n\tfunction parseKeyframeTrack( json ) {\r\n\r\n\t\tif ( json.type === undefined ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );\r\n\r\n\t\t}\r\n\r\n\t\tvar trackType = getTrackTypeForValueTypeName( json.type );\r\n\r\n\t\tif ( json.times === undefined ) {\r\n\r\n\t\t\tvar times = [], values = [];\r\n\r\n\t\t\tAnimationUtils.flattenJSON( json.keys, times, values, 'value' );\r\n\r\n\t\t\tjson.times = times;\r\n\t\t\tjson.values = values;\r\n\r\n\t\t}\r\n\r\n\t\t// derived classes can define a static parse method\r\n\t\tif ( trackType.parse !== undefined ) {\r\n\r\n\t\t\treturn trackType.parse( json );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// by default, we assume a constructor compatible with the base\r\n\t\t\treturn new trackType( json.name, json.times, json.values, json.interpolation );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationClip, {\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar tracks = [],\r\n\t\t\t\tjsonTracks = json.tracks,\r\n\t\t\t\tframeTime = 1.0 / ( json.fps || 1.0 );\r\n\r\n\t\t\tfor ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\ttracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( json.name, json.duration, tracks );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( clip ) {\r\n\r\n\t\t\tvar tracks = [],\r\n\t\t\t\tclipTracks = clip.tracks;\r\n\r\n\t\t\tvar json = {\r\n\r\n\t\t\t\t'name': clip.name,\r\n\t\t\t\t'duration': clip.duration,\r\n\t\t\t\t'tracks': tracks,\r\n\t\t\t\t'uuid': clip.uuid\r\n\r\n\t\t\t};\r\n\r\n\t\t\tfor ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\ttracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn json;\r\n\r\n\t\t},\r\n\r\n\t\tCreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {\r\n\r\n\t\t\tvar numMorphTargets = morphTargetSequence.length;\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < numMorphTargets; i ++ ) {\r\n\r\n\t\t\t\tvar times = [];\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\ttimes.push(\r\n\t\t\t\t\t( i + numMorphTargets - 1 ) % numMorphTargets,\r\n\t\t\t\t\ti,\r\n\t\t\t\t\t( i + 1 ) % numMorphTargets );\r\n\r\n\t\t\t\tvalues.push( 0, 1, 0 );\r\n\r\n\t\t\t\tvar order = AnimationUtils.getKeyframeOrder( times );\r\n\t\t\t\ttimes = AnimationUtils.sortedArray( times, 1, order );\r\n\t\t\t\tvalues = AnimationUtils.sortedArray( values, 1, order );\r\n\r\n\t\t\t\t// if there is a key at the first frame, duplicate it as the\r\n\t\t\t\t// last frame as well for perfect loop.\r\n\t\t\t\tif ( ! noLoop && times[ 0 ] === 0 ) {\r\n\r\n\t\t\t\t\ttimes.push( numMorphTargets );\r\n\t\t\t\t\tvalues.push( values[ 0 ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttracks.push(\r\n\t\t\t\t\tnew NumberKeyframeTrack(\r\n\t\t\t\t\t\t'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',\r\n\t\t\t\t\t\ttimes, values\r\n\t\t\t\t\t).scale( 1.0 / fps ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( name, - 1, tracks );\r\n\r\n\t\t},\r\n\r\n\t\tfindByName: function ( objectOrClipArray, name ) {\r\n\r\n\t\t\tvar clipArray = objectOrClipArray;\r\n\r\n\t\t\tif ( ! Array.isArray( objectOrClipArray ) ) {\r\n\r\n\t\t\t\tvar o = objectOrClipArray;\r\n\t\t\t\tclipArray = o.geometry && o.geometry.animations || o.animations;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < clipArray.length; i ++ ) {\r\n\r\n\t\t\t\tif ( clipArray[ i ].name === name ) {\r\n\r\n\t\t\t\t\treturn clipArray[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\tCreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {\r\n\r\n\t\t\tvar animationToMorphTargets = {};\r\n\r\n\t\t\t// tested with https://regex101.com/ on trick sequences\r\n\t\t\t// such flamingo_flyA_003, flamingo_run1_003, crdeath0059\r\n\t\t\tvar pattern = /^([\\w-]*?)([\\d]+)$/;\r\n\r\n\t\t\t// sort morph target names into animation groups based\r\n\t\t\t// patterns like Walk_001, Walk_002, Run_001, Run_002\r\n\t\t\tfor ( var i = 0, il = morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphTarget = morphTargets[ i ];\r\n\t\t\t\tvar parts = morphTarget.name.match( pattern );\r\n\r\n\t\t\t\tif ( parts && parts.length > 1 ) {\r\n\r\n\t\t\t\t\tvar name = parts[ 1 ];\r\n\r\n\t\t\t\t\tvar animationMorphTargets = animationToMorphTargets[ name ];\r\n\t\t\t\t\tif ( ! animationMorphTargets ) {\r\n\r\n\t\t\t\t\t\tanimationToMorphTargets[ name ] = animationMorphTargets = [];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tanimationMorphTargets.push( morphTarget );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar clips = [];\r\n\r\n\t\t\tfor ( var name in animationToMorphTargets ) {\r\n\r\n\t\t\t\tclips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn clips;\r\n\r\n\t\t},\r\n\r\n\t\t// parse the animation.hierarchy format\r\n\t\tparseAnimation: function ( animation, bones ) {\r\n\r\n\t\t\tif ( ! animation ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {\r\n\r\n\t\t\t\t// only return track if there are actually keys.\r\n\t\t\t\tif ( animationKeys.length !== 0 ) {\r\n\r\n\t\t\t\t\tvar times = [];\r\n\t\t\t\t\tvar values = [];\r\n\r\n\t\t\t\t\tAnimationUtils.flattenJSON( animationKeys, times, values, propertyName );\r\n\r\n\t\t\t\t\t// empty keys are filtered out, so check again\r\n\t\t\t\t\tif ( times.length !== 0 ) {\r\n\r\n\t\t\t\t\t\tdestTracks.push( new trackType( trackName, times, values ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tvar clipName = animation.name || 'default';\r\n\t\t\t// automatic length determination in AnimationClip.\r\n\t\t\tvar duration = animation.length || - 1;\r\n\t\t\tvar fps = animation.fps || 30;\r\n\r\n\t\t\tvar hierarchyTracks = animation.hierarchy || [];\r\n\r\n\t\t\tfor ( var h = 0; h < hierarchyTracks.length; h ++ ) {\r\n\r\n\t\t\t\tvar animationKeys = hierarchyTracks[ h ].keys;\r\n\r\n\t\t\t\t// skip empty tracks\r\n\t\t\t\tif ( ! animationKeys || animationKeys.length === 0 ) { continue; }\r\n\r\n\t\t\t\t// process morph targets\r\n\t\t\t\tif ( animationKeys[ 0 ].morphTargets ) {\r\n\r\n\t\t\t\t\t// figure out all morph targets used in this track\r\n\t\t\t\t\tvar morphTargetNames = {};\r\n\r\n\t\t\t\t\tfor ( var k = 0; k < animationKeys.length; k ++ ) {\r\n\r\n\t\t\t\t\t\tif ( animationKeys[ k ].morphTargets ) {\r\n\r\n\t\t\t\t\t\t\tfor ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tmorphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// create a track for each morph target with all zero\r\n\t\t\t\t\t// morphTargetInfluences except for the keys in which\r\n\t\t\t\t\t// the morphTarget is named.\r\n\t\t\t\t\tfor ( var morphTargetName in morphTargetNames ) {\r\n\r\n\t\t\t\t\t\tvar times = [];\r\n\t\t\t\t\t\tvar values = [];\r\n\r\n\t\t\t\t\t\tfor ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {\r\n\r\n\t\t\t\t\t\t\tvar animationKey = animationKeys[ k ];\r\n\r\n\t\t\t\t\t\t\ttimes.push( animationKey.time );\r\n\t\t\t\t\t\t\tvalues.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tduration = morphTargetNames.length * ( fps || 1.0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// ...assume skeletal animation\r\n\r\n\t\t\t\t\tvar boneName = '.bones[' + bones[ h ].name + ']';\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tVectorKeyframeTrack, boneName + '.position',\r\n\t\t\t\t\t\tanimationKeys, 'pos', tracks );\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tQuaternionKeyframeTrack, boneName + '.quaternion',\r\n\t\t\t\t\t\tanimationKeys, 'rot', tracks );\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tVectorKeyframeTrack, boneName + '.scale',\r\n\t\t\t\t\t\tanimationKeys, 'scl', tracks );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tracks.length === 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar clip = new AnimationClip( clipName, duration, tracks );\r\n\r\n\t\t\treturn clip;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( AnimationClip.prototype, {\r\n\r\n\t\tresetDuration: function () {\r\n\r\n\t\t\tvar tracks = this.tracks, duration = 0;\r\n\r\n\t\t\tfor ( var i = 0, n = tracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar track = this.tracks[ i ];\r\n\r\n\t\t\t\tduration = Math.max( duration, track.times[ track.times.length - 1 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.duration = duration;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttrim: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tthis.tracks[ i ].trim( 0, this.duration );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tvalidate: function () {\r\n\r\n\t\t\tvar valid = true;\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tvalid = valid && this.tracks[ i ].validate();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn valid;\r\n\r\n\t\t},\r\n\r\n\t\toptimize: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tthis.tracks[ i ].optimize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\ttracks.push( this.tracks[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( this.name, this.duration, tracks );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar Cache = {\r\n\r\n\t\tenabled: false,\r\n\r\n\t\tfiles: {},\r\n\r\n\t\tadd: function ( key, file ) {\r\n\r\n\t\t\tif ( this.enabled === false ) { return; }\r\n\r\n\t\t\t// console.log( 'THREE.Cache', 'Adding key:', key );\r\n\r\n\t\t\tthis.files[ key ] = file;\r\n\r\n\t\t},\r\n\r\n\t\tget: function ( key ) {\r\n\r\n\t\t\tif ( this.enabled === false ) { return; }\r\n\r\n\t\t\t// console.log( 'THREE.Cache', 'Checking key:', key );\r\n\r\n\t\t\treturn this.files[ key ];\r\n\r\n\t\t},\r\n\r\n\t\tremove: function ( key ) {\r\n\r\n\t\t\tdelete this.files[ key ];\r\n\r\n\t\t},\r\n\r\n\t\tclear: function () {\r\n\r\n\t\t\tthis.files = {};\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction LoadingManager( onLoad, onProgress, onError ) {\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar isLoading = false;\r\n\t\tvar itemsLoaded = 0;\r\n\t\tvar itemsTotal = 0;\r\n\t\tvar urlModifier = undefined;\r\n\t\tvar handlers = [];\r\n\r\n\t\t// Refer to #5689 for the reason why we don't set .onStart\r\n\t\t// in the constructor\r\n\r\n\t\tthis.onStart = undefined;\r\n\t\tthis.onLoad = onLoad;\r\n\t\tthis.onProgress = onProgress;\r\n\t\tthis.onError = onError;\r\n\r\n\t\tthis.itemStart = function ( url ) {\r\n\r\n\t\t\titemsTotal ++;\r\n\r\n\t\t\tif ( isLoading === false ) {\r\n\r\n\t\t\t\tif ( scope.onStart !== undefined ) {\r\n\r\n\t\t\t\t\tscope.onStart( url, itemsLoaded, itemsTotal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tisLoading = true;\r\n\r\n\t\t};\r\n\r\n\t\tthis.itemEnd = function ( url ) {\r\n\r\n\t\t\titemsLoaded ++;\r\n\r\n\t\t\tif ( scope.onProgress !== undefined ) {\r\n\r\n\t\t\t\tscope.onProgress( url, itemsLoaded, itemsTotal );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( itemsLoaded === itemsTotal ) {\r\n\r\n\t\t\t\tisLoading = false;\r\n\r\n\t\t\t\tif ( scope.onLoad !== undefined ) {\r\n\r\n\t\t\t\t\tscope.onLoad();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.itemError = function ( url ) {\r\n\r\n\t\t\tif ( scope.onError !== undefined ) {\r\n\r\n\t\t\t\tscope.onError( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.resolveURL = function ( url ) {\r\n\r\n\t\t\tif ( urlModifier ) {\r\n\r\n\t\t\t\treturn urlModifier( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn url;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setURLModifier = function ( transform ) {\r\n\r\n\t\t\turlModifier = transform;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.addHandler = function ( regex, loader ) {\r\n\r\n\t\t\thandlers.push( regex, loader );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.removeHandler = function ( regex ) {\r\n\r\n\t\t\tvar index = handlers.indexOf( regex );\r\n\r\n\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\thandlers.splice( index, 2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getHandler = function ( file ) {\r\n\r\n\t\t\tfor ( var i = 0, l = handlers.length; i < l; i += 2 ) {\r\n\r\n\t\t\t\tvar regex = handlers[ i ];\r\n\t\t\t\tvar loader = handlers[ i + 1 ];\r\n\r\n\t\t\t\tif ( regex.global ) { regex.lastIndex = 0; } // see #17920\r\n\r\n\t\t\t\tif ( regex.test( file ) ) {\r\n\r\n\t\t\t\t\treturn loader;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tvar DefaultLoadingManager = new LoadingManager();\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Loader( manager ) {\r\n\r\n\t\tthis.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;\r\n\r\n\t\tthis.crossOrigin = 'anonymous';\r\n\t\tthis.path = '';\r\n\t\tthis.resourcePath = '';\r\n\r\n\t}\r\n\r\n\tObject.assign( Loader.prototype, {\r\n\r\n\t\tload: function ( /* url, onLoad, onProgress, onError */ ) {},\r\n\r\n\t\tparse: function ( /* data */ ) {},\r\n\r\n\t\tsetCrossOrigin: function ( crossOrigin ) {\r\n\r\n\t\t\tthis.crossOrigin = crossOrigin;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetPath: function ( path ) {\r\n\r\n\t\t\tthis.path = path;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetResourcePath: function ( resourcePath ) {\r\n\r\n\t\t\tthis.resourcePath = resourcePath;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar loading = {};\r\n\r\n\tfunction FileLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tFileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: FileLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( url === undefined ) { url = ''; }\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Check if request is duplicate\r\n\r\n\t\t\tif ( loading[ url ] !== undefined ) {\r\n\r\n\t\t\t\tloading[ url ].push( {\r\n\r\n\t\t\t\t\tonLoad: onLoad,\r\n\t\t\t\t\tonProgress: onProgress,\r\n\t\t\t\t\tonError: onError\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Check for data: URI\r\n\t\t\tvar dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\r\n\t\t\tvar dataUriRegexResult = url.match( dataUriRegex );\r\n\r\n\t\t\t// Safari can not handle Data URIs through XMLHttpRequest so process manually\r\n\t\t\tif ( dataUriRegexResult ) {\r\n\r\n\t\t\t\tvar mimeType = dataUriRegexResult[ 1 ];\r\n\t\t\t\tvar isBase64 = !! dataUriRegexResult[ 2 ];\r\n\t\t\t\tvar data = dataUriRegexResult[ 3 ];\r\n\r\n\t\t\t\tdata = decodeURIComponent( data );\r\n\r\n\t\t\t\tif ( isBase64 ) { data = atob( data ); }\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tvar response;\r\n\t\t\t\t\tvar responseType = ( this.responseType || '' ).toLowerCase();\r\n\r\n\t\t\t\t\tswitch ( responseType ) {\r\n\r\n\t\t\t\t\t\tcase 'arraybuffer':\r\n\t\t\t\t\t\tcase 'blob':\r\n\r\n\t\t\t\t\t\t\tvar view = new Uint8Array( data.length );\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0; i < data.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tview[ i ] = data.charCodeAt( i );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif ( responseType === 'blob' ) {\r\n\r\n\t\t\t\t\t\t\t\tresponse = new Blob( [ view.buffer ], { type: mimeType } );\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tresponse = view.buffer;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'document':\r\n\r\n\t\t\t\t\t\t\tvar parser = new DOMParser();\r\n\t\t\t\t\t\t\tresponse = parser.parseFromString( data, mimeType );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'json':\r\n\r\n\t\t\t\t\t\t\tresponse = JSON.parse( data );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault: // 'text' or other\r\n\r\n\t\t\t\t\t\t\tresponse = data;\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Wait for next browser tick like standard XMLHttpRequest event dispatching does\r\n\t\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( response ); }\r\n\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}, 0 );\r\n\r\n\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\t// Wait for next browser tick like standard XMLHttpRequest event dispatching does\r\n\t\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\t\tif ( onError ) { onError( error ); }\r\n\r\n\t\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}, 0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Initialise array for duplicate requests\r\n\r\n\t\t\t\tloading[ url ] = [];\r\n\r\n\t\t\t\tloading[ url ].push( {\r\n\r\n\t\t\t\t\tonLoad: onLoad,\r\n\t\t\t\t\tonProgress: onProgress,\r\n\t\t\t\t\tonError: onError\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\tvar request = new XMLHttpRequest();\r\n\r\n\t\t\t\trequest.open( 'GET', url, true );\r\n\r\n\t\t\t\trequest.addEventListener( 'load', function ( event ) {\r\n\r\n\t\t\t\t\tvar response = this.response;\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tif ( this.status === 200 || this.status === 0 ) {\r\n\r\n\t\t\t\t\t\t// Some browsers return HTTP Status 0 when using non-http protocol\r\n\t\t\t\t\t\t// e.g. 'file://' or 'data://'. Handle as success.\r\n\r\n\t\t\t\t\t\tif ( this.status === 0 ) { console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); }\r\n\r\n\t\t\t\t\t\t// Add to cache only on HTTP success, so that we do not cache\r\n\t\t\t\t\t\t// error response bodies as proper responses to requests.\r\n\t\t\t\t\t\tCache.add( url, response );\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\t\tif ( callback.onLoad ) { callback.onLoad( response ); }\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'progress', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onProgress ) { callback.onProgress( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'error', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'abort', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\tif ( this.responseType !== undefined ) { request.responseType = this.responseType; }\r\n\t\t\t\tif ( this.withCredentials !== undefined ) { request.withCredentials = this.withCredentials; }\r\n\r\n\t\t\t\tif ( request.overrideMimeType ) { request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); }\r\n\r\n\t\t\t\tfor ( var header in this.requestHeader ) {\r\n\r\n\t\t\t\t\trequest.setRequestHeader( header, this.requestHeader[ header ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\trequest.send( null );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\treturn request;\r\n\r\n\t\t},\r\n\r\n\t\tsetResponseType: function ( value ) {\r\n\r\n\t\t\tthis.responseType = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetWithCredentials: function ( value ) {\r\n\r\n\t\t\tthis.withCredentials = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMimeType: function ( value ) {\r\n\r\n\t\t\tthis.mimeType = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRequestHeader: function ( value ) {\r\n\r\n\t\t\tthis.requestHeader = value;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io/\r\n\t */\r\n\r\n\tfunction AnimationLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tAnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: AnimationLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar animations = [];\r\n\r\n\t\t\tfor ( var i = 0; i < json.length; i ++ ) {\r\n\r\n\t\t\t\tvar clip = AnimationClip.parse( json[ i ] );\r\n\r\n\t\t\t\tanimations.push( clip );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn animations;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * Abstract Base class to block based textures loader (dds, pvr, ...)\r\n\t *\r\n\t * Sub classes have to implement the parse() method which will be used in load().\r\n\t */\r\n\r\n\tfunction CompressedTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tCompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: CompressedTextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar images = [];\r\n\r\n\t\t\tvar texture = new CompressedTexture();\r\n\t\t\ttexture.image = images;\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\r\n\t\t\tfunction loadTexture( i ) {\r\n\r\n\t\t\t\tloader.load( url[ i ], function ( buffer ) {\r\n\r\n\t\t\t\t\tvar texDatas = scope.parse( buffer, true );\r\n\r\n\t\t\t\t\timages[ i ] = {\r\n\t\t\t\t\t\twidth: texDatas.width,\r\n\t\t\t\t\t\theight: texDatas.height,\r\n\t\t\t\t\t\tformat: texDatas.format,\r\n\t\t\t\t\t\tmipmaps: texDatas.mipmaps\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t\tloaded += 1;\r\n\r\n\t\t\t\t\tif ( loaded === 6 ) {\r\n\r\n\t\t\t\t\t\tif ( texDatas.mipmapCount === 1 )\r\n\t\t\t\t\t\t\t{ texture.minFilter = LinearFilter; }\r\n\r\n\t\t\t\t\t\ttexture.format = texDatas.format;\r\n\t\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, onProgress, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( Array.isArray( url ) ) {\r\n\r\n\t\t\t\tvar loaded = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, il = url.length; i < il; ++ i ) {\r\n\r\n\t\t\t\t\tloadTexture( i );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// compressed cubemap texture stored in a single DDS file\r\n\r\n\t\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\t\tvar texDatas = scope.parse( buffer, true );\r\n\r\n\t\t\t\t\tif ( texDatas.isCubemap ) {\r\n\r\n\t\t\t\t\t\tvar faces = texDatas.mipmaps.length / texDatas.mipmapCount;\r\n\r\n\t\t\t\t\t\tfor ( var f = 0; f < faces; f ++ ) {\r\n\r\n\t\t\t\t\t\t\timages[ f ] = { mipmaps: [] };\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0; i < texDatas.mipmapCount; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\timages[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );\r\n\t\t\t\t\t\t\t\timages[ f ].format = texDatas.format;\r\n\t\t\t\t\t\t\t\timages[ f ].width = texDatas.width;\r\n\t\t\t\t\t\t\t\timages[ f ].height = texDatas.height;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ttexture.image.width = texDatas.width;\r\n\t\t\t\t\t\ttexture.image.height = texDatas.height;\r\n\t\t\t\t\t\ttexture.mipmaps = texDatas.mipmaps;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( texDatas.mipmapCount === 1 ) {\r\n\r\n\t\t\t\t\t\ttexture.minFilter = LinearFilter;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.format = texDatas.format;\r\n\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t}, onProgress, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Nikos M. / https://github.com/foo123/\r\n\t *\r\n\t * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)\r\n\t *\r\n\t * Sub classes have to implement the parse() method which will be used in load().\r\n\t */\r\n\r\n\tfunction DataTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tDataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: DataTextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar texture = new DataTexture();\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\tvar texData = scope.parse( buffer );\r\n\r\n\t\t\t\tif ( ! texData ) { return; }\r\n\r\n\t\t\t\tif ( texData.image !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.image = texData.image;\r\n\r\n\t\t\t\t} else if ( texData.data !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.image.width = texData.width;\r\n\t\t\t\t\ttexture.image.height = texData.height;\r\n\t\t\t\t\ttexture.image.data = texData.data;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;\r\n\t\t\t\ttexture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;\r\n\r\n\t\t\t\ttexture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;\r\n\t\t\t\ttexture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;\r\n\r\n\t\t\t\ttexture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;\r\n\r\n\t\t\t\tif ( texData.format !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.format = texData.format;\r\n\r\n\t\t\t\t}\r\n\t\t\t\tif ( texData.type !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.type = texData.type;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texData.mipmaps !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.mipmaps = texData.mipmaps;\r\n\t\t\t\t\ttexture.minFilter = LinearMipmapLinearFilter; // presumably...\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texData.mipmapCount === 1 ) {\r\n\r\n\t\t\t\t\ttexture.minFilter = LinearFilter;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( texture, texData ); }\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ImageLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ImageLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );\r\n\r\n\t\t\tfunction onImageLoad() {\r\n\r\n\t\t\t\timage.removeEventListener( 'load', onImageLoad, false );\r\n\t\t\t\timage.removeEventListener( 'error', onImageError, false );\r\n\r\n\t\t\t\tCache.add( url, this );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( this ); }\r\n\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction onImageError( event ) {\r\n\r\n\t\t\t\timage.removeEventListener( 'load', onImageLoad, false );\r\n\t\t\t\timage.removeEventListener( 'error', onImageError, false );\r\n\r\n\t\t\t\tif ( onError ) { onError( event ); }\r\n\r\n\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\timage.addEventListener( 'load', onImageLoad, false );\r\n\t\t\timage.addEventListener( 'error', onImageError, false );\r\n\r\n\t\t\tif ( url.substr( 0, 5 ) !== 'data:' ) {\r\n\r\n\t\t\t\tif ( this.crossOrigin !== undefined ) { image.crossOrigin = this.crossOrigin; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\timage.src = url;\r\n\r\n\t\t\treturn image;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction CubeTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: CubeTextureLoader,\r\n\r\n\t\tload: function ( urls, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar texture = new CubeTexture();\r\n\r\n\t\t\tvar loader = new ImageLoader( this.manager );\r\n\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\t\t\tloader.setPath( this.path );\r\n\r\n\t\t\tvar loaded = 0;\r\n\r\n\t\t\tfunction loadTexture( i ) {\r\n\r\n\t\t\t\tloader.load( urls[ i ], function ( image ) {\r\n\r\n\t\t\t\t\ttexture.images[ i ] = image;\r\n\r\n\t\t\t\t\tloaded ++;\r\n\r\n\t\t\t\t\tif ( loaded === 6 ) {\r\n\r\n\t\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, undefined, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < urls.length; ++ i ) {\r\n\r\n\t\t\t\tloadTexture( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction TextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: TextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar texture = new Texture();\r\n\r\n\t\t\tvar loader = new ImageLoader( this.manager );\r\n\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\t\t\tloader.setPath( this.path );\r\n\r\n\t\t\tloader.load( url, function ( image ) {\r\n\r\n\t\t\t\ttexture.image = image;\r\n\r\n\t\t\t\t// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.\r\n\t\t\t\tvar isJPEG = url.search( /\\.jpe?g($|\\?)/i ) > 0 || url.search( /^data\\:image\\/jpeg/ ) === 0;\r\n\r\n\t\t\t\ttexture.format = isJPEG ? RGBFormat : RGBAFormat;\r\n\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) {\r\n\r\n\t\t\t\t\tonLoad( texture );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Extensible curve object\r\n\t *\r\n\t * Some common of curve methods:\r\n\t * .getPoint( t, optionalTarget ), .getTangent( t )\r\n\t * .getPointAt( u, optionalTarget ), .getTangentAt( u )\r\n\t * .getPoints(), .getSpacedPoints()\r\n\t * .getLength()\r\n\t * .updateArcLengths()\r\n\t *\r\n\t * This following curves inherit from THREE.Curve:\r\n\t *\r\n\t * -- 2D curves --\r\n\t * THREE.ArcCurve\r\n\t * THREE.CubicBezierCurve\r\n\t * THREE.EllipseCurve\r\n\t * THREE.LineCurve\r\n\t * THREE.QuadraticBezierCurve\r\n\t * THREE.SplineCurve\r\n\t *\r\n\t * -- 3D curves --\r\n\t * THREE.CatmullRomCurve3\r\n\t * THREE.CubicBezierCurve3\r\n\t * THREE.LineCurve3\r\n\t * THREE.QuadraticBezierCurve3\r\n\t *\r\n\t * A series of curves can be represented as a THREE.CurvePath.\r\n\t *\r\n\t **/\r\n\r\n\t/**************************************************************\r\n\t *\tAbstract Curve base class\r\n\t **************************************************************/\r\n\r\n\tfunction Curve() {\r\n\r\n\t\tthis.type = 'Curve';\r\n\r\n\t\tthis.arcLengthDivisions = 200;\r\n\r\n\t}\r\n\r\n\tObject.assign( Curve.prototype, {\r\n\r\n\t\t// Virtual base class method to overwrite and implement in subclasses\r\n\t\t//\t- t [0 .. 1]\r\n\r\n\t\tgetPoint: function ( /* t, optionalTarget */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .getPoint() not implemented.' );\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\t// Get point at relative position in curve according to arc length\r\n\t\t// - u [0 .. 1]\r\n\r\n\t\tgetPointAt: function ( u, optionalTarget ) {\r\n\r\n\t\t\tvar t = this.getUtoTmapping( u );\r\n\t\t\treturn this.getPoint( t, optionalTarget );\r\n\r\n\t\t},\r\n\r\n\t\t// Get sequence of points using getPoint( t )\r\n\r\n\t\tgetPoints: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = 5; }\r\n\r\n\t\t\tvar points = [];\r\n\r\n\t\t\tfor ( var d = 0; d <= divisions; d ++ ) {\r\n\r\n\t\t\t\tpoints.push( this.getPoint( d / divisions ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\t// Get sequence of points using getPointAt( u )\r\n\r\n\t\tgetSpacedPoints: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = 5; }\r\n\r\n\t\t\tvar points = [];\r\n\r\n\t\t\tfor ( var d = 0; d <= divisions; d ++ ) {\r\n\r\n\t\t\t\tpoints.push( this.getPointAt( d / divisions ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\t// Get total curve arc length\r\n\r\n\t\tgetLength: function () {\r\n\r\n\t\t\tvar lengths = this.getLengths();\r\n\t\t\treturn lengths[ lengths.length - 1 ];\r\n\r\n\t\t},\r\n\r\n\t\t// Get list of cumulative segment lengths\r\n\r\n\t\tgetLengths: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = this.arcLengthDivisions; }\r\n\r\n\t\t\tif ( this.cacheArcLengths &&\r\n\t\t\t\t( this.cacheArcLengths.length === divisions + 1 ) &&\r\n\t\t\t\t! this.needsUpdate ) {\r\n\r\n\t\t\t\treturn this.cacheArcLengths;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.needsUpdate = false;\r\n\r\n\t\t\tvar cache = [];\r\n\t\t\tvar current, last = this.getPoint( 0 );\r\n\t\t\tvar p, sum = 0;\r\n\r\n\t\t\tcache.push( 0 );\r\n\r\n\t\t\tfor ( p = 1; p <= divisions; p ++ ) {\r\n\r\n\t\t\t\tcurrent = this.getPoint( p / divisions );\r\n\t\t\t\tsum += current.distanceTo( last );\r\n\t\t\t\tcache.push( sum );\r\n\t\t\t\tlast = current;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cacheArcLengths = cache;\r\n\r\n\t\t\treturn cache; // { sums: cache, sum: sum }; Sum is in the last element.\r\n\r\n\t\t},\r\n\r\n\t\tupdateArcLengths: function () {\r\n\r\n\t\t\tthis.needsUpdate = true;\r\n\t\t\tthis.getLengths();\r\n\r\n\t\t},\r\n\r\n\t\t// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant\r\n\r\n\t\tgetUtoTmapping: function ( u, distance ) {\r\n\r\n\t\t\tvar arcLengths = this.getLengths();\r\n\r\n\t\t\tvar i = 0, il = arcLengths.length;\r\n\r\n\t\t\tvar targetArcLength; // The targeted u distance value to get\r\n\r\n\t\t\tif ( distance ) {\r\n\r\n\t\t\t\ttargetArcLength = distance;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttargetArcLength = u * arcLengths[ il - 1 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// binary search for the index with largest value smaller than target u distance\r\n\r\n\t\t\tvar low = 0, high = il - 1, comparison;\r\n\r\n\t\t\twhile ( low <= high ) {\r\n\r\n\t\t\t\ti = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats\r\n\r\n\t\t\t\tcomparison = arcLengths[ i ] - targetArcLength;\r\n\r\n\t\t\t\tif ( comparison < 0 ) {\r\n\r\n\t\t\t\t\tlow = i + 1;\r\n\r\n\t\t\t\t} else if ( comparison > 0 ) {\r\n\r\n\t\t\t\t\thigh = i - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\thigh = i;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t// DONE\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\ti = high;\r\n\r\n\t\t\tif ( arcLengths[ i ] === targetArcLength ) {\r\n\r\n\t\t\t\treturn i / ( il - 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// we could get finer grain at lengths, or use simple interpolation between two points\r\n\r\n\t\t\tvar lengthBefore = arcLengths[ i ];\r\n\t\t\tvar lengthAfter = arcLengths[ i + 1 ];\r\n\r\n\t\t\tvar segmentLength = lengthAfter - lengthBefore;\r\n\r\n\t\t\t// determine where we are between the 'before' and 'after' points\r\n\r\n\t\t\tvar segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;\r\n\r\n\t\t\t// add that fractional amount to t\r\n\r\n\t\t\tvar t = ( i + segmentFraction ) / ( il - 1 );\r\n\r\n\t\t\treturn t;\r\n\r\n\t\t},\r\n\r\n\t\t// Returns a unit vector tangent at t\r\n\t\t// In case any sub curve does not implement its tangent derivation,\r\n\t\t// 2 points a small delta apart will be used to find its gradient\r\n\t\t// which seems to give a reasonable approximation\r\n\r\n\t\tgetTangent: function ( t ) {\r\n\r\n\t\t\tvar delta = 0.0001;\r\n\t\t\tvar t1 = t - delta;\r\n\t\t\tvar t2 = t + delta;\r\n\r\n\t\t\t// Capping in case of danger\r\n\r\n\t\t\tif ( t1 < 0 ) { t1 = 0; }\r\n\t\t\tif ( t2 > 1 ) { t2 = 1; }\r\n\r\n\t\t\tvar pt1 = this.getPoint( t1 );\r\n\t\t\tvar pt2 = this.getPoint( t2 );\r\n\r\n\t\t\tvar vec = pt2.clone().sub( pt1 );\r\n\t\t\treturn vec.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tgetTangentAt: function ( u ) {\r\n\r\n\t\t\tvar t = this.getUtoTmapping( u );\r\n\t\t\treturn this.getTangent( t );\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFrenetFrames: function ( segments, closed ) {\r\n\r\n\t\t\t// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf\r\n\r\n\t\t\tvar normal = new Vector3();\r\n\r\n\t\t\tvar tangents = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar binormals = [];\r\n\r\n\t\t\tvar vec = new Vector3();\r\n\t\t\tvar mat = new Matrix4();\r\n\r\n\t\t\tvar i, u, theta;\r\n\r\n\t\t\t// compute the tangent vectors for each segment on the curve\r\n\r\n\t\t\tfor ( i = 0; i <= segments; i ++ ) {\r\n\r\n\t\t\t\tu = i / segments;\r\n\r\n\t\t\t\ttangents[ i ] = this.getTangentAt( u );\r\n\t\t\t\ttangents[ i ].normalize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// select an initial normal vector perpendicular to the first tangent vector,\r\n\t\t\t// and in the direction of the minimum tangent xyz component\r\n\r\n\t\t\tnormals[ 0 ] = new Vector3();\r\n\t\t\tbinormals[ 0 ] = new Vector3();\r\n\t\t\tvar min = Number.MAX_VALUE;\r\n\t\t\tvar tx = Math.abs( tangents[ 0 ].x );\r\n\t\t\tvar ty = Math.abs( tangents[ 0 ].y );\r\n\t\t\tvar tz = Math.abs( tangents[ 0 ].z );\r\n\r\n\t\t\tif ( tx <= min ) {\r\n\r\n\t\t\t\tmin = tx;\r\n\t\t\t\tnormal.set( 1, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ty <= min ) {\r\n\r\n\t\t\t\tmin = ty;\r\n\t\t\t\tnormal.set( 0, 1, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tz <= min ) {\r\n\r\n\t\t\t\tnormal.set( 0, 0, 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvec.crossVectors( tangents[ 0 ], normal ).normalize();\r\n\r\n\t\t\tnormals[ 0 ].crossVectors( tangents[ 0 ], vec );\r\n\t\t\tbinormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );\r\n\r\n\r\n\t\t\t// compute the slowly-varying normal and binormal vectors for each segment on the curve\r\n\r\n\t\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\t\tnormals[ i ] = normals[ i - 1 ].clone();\r\n\r\n\t\t\t\tbinormals[ i ] = binormals[ i - 1 ].clone();\r\n\r\n\t\t\t\tvec.crossVectors( tangents[ i - 1 ], tangents[ i ] );\r\n\r\n\t\t\t\tif ( vec.length() > Number.EPSILON ) {\r\n\r\n\t\t\t\t\tvec.normalize();\r\n\r\n\t\t\t\t\ttheta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors\r\n\r\n\t\t\t\t\tnormals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbinormals[ i ].crossVectors( tangents[ i ], normals[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same\r\n\r\n\t\t\tif ( closed === true ) {\r\n\r\n\t\t\t\ttheta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );\r\n\t\t\t\ttheta /= segments;\r\n\r\n\t\t\t\tif ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {\r\n\r\n\t\t\t\t\ttheta = - theta;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\t\t\t// twist a little...\r\n\t\t\t\t\tnormals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );\r\n\t\t\t\t\tbinormals[ i ].crossVectors( tangents[ i ], normals[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttangents: tangents,\r\n\t\t\t\tnormals: normals,\r\n\t\t\t\tbinormals: binormals\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.arcLengthDivisions = source.arcLengthDivisions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Curve',\r\n\t\t\t\t\tgenerator: 'Curve.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tdata.arcLengthDivisions = this.arcLengthDivisions;\r\n\t\t\tdata.type = this.type;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tthis.arcLengthDivisions = json.arcLengthDivisions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tfunction EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'EllipseCurve';\r\n\r\n\t\tthis.aX = aX || 0;\r\n\t\tthis.aY = aY || 0;\r\n\r\n\t\tthis.xRadius = xRadius || 1;\r\n\t\tthis.yRadius = yRadius || 1;\r\n\r\n\t\tthis.aStartAngle = aStartAngle || 0;\r\n\t\tthis.aEndAngle = aEndAngle || 2 * Math.PI;\r\n\r\n\t\tthis.aClockwise = aClockwise || false;\r\n\r\n\t\tthis.aRotation = aRotation || 0;\r\n\r\n\t}\r\n\r\n\tEllipseCurve.prototype = Object.create( Curve.prototype );\r\n\tEllipseCurve.prototype.constructor = EllipseCurve;\r\n\r\n\tEllipseCurve.prototype.isEllipseCurve = true;\r\n\r\n\tEllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar twoPi = Math.PI * 2;\r\n\t\tvar deltaAngle = this.aEndAngle - this.aStartAngle;\r\n\t\tvar samePoints = Math.abs( deltaAngle ) < Number.EPSILON;\r\n\r\n\t\t// ensures that deltaAngle is 0 .. 2 PI\r\n\t\twhile ( deltaAngle < 0 ) { deltaAngle += twoPi; }\r\n\t\twhile ( deltaAngle > twoPi ) { deltaAngle -= twoPi; }\r\n\r\n\t\tif ( deltaAngle < Number.EPSILON ) {\r\n\r\n\t\t\tif ( samePoints ) {\r\n\r\n\t\t\t\tdeltaAngle = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdeltaAngle = twoPi;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.aClockwise === true && ! samePoints ) {\r\n\r\n\t\t\tif ( deltaAngle === twoPi ) {\r\n\r\n\t\t\t\tdeltaAngle = - twoPi;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdeltaAngle = deltaAngle - twoPi;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar angle = this.aStartAngle + t * deltaAngle;\r\n\t\tvar x = this.aX + this.xRadius * Math.cos( angle );\r\n\t\tvar y = this.aY + this.yRadius * Math.sin( angle );\r\n\r\n\t\tif ( this.aRotation !== 0 ) {\r\n\r\n\t\t\tvar cos = Math.cos( this.aRotation );\r\n\t\t\tvar sin = Math.sin( this.aRotation );\r\n\r\n\t\t\tvar tx = x - this.aX;\r\n\t\t\tvar ty = y - this.aY;\r\n\r\n\t\t\t// Rotate the point about the center of the ellipse.\r\n\t\t\tx = tx * cos - ty * sin + this.aX;\r\n\t\t\ty = tx * sin + ty * cos + this.aY;\r\n\r\n\t\t}\r\n\r\n\t\treturn point.set( x, y );\r\n\r\n\t};\r\n\r\n\tEllipseCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.aX = source.aX;\r\n\t\tthis.aY = source.aY;\r\n\r\n\t\tthis.xRadius = source.xRadius;\r\n\t\tthis.yRadius = source.yRadius;\r\n\r\n\t\tthis.aStartAngle = source.aStartAngle;\r\n\t\tthis.aEndAngle = source.aEndAngle;\r\n\r\n\t\tthis.aClockwise = source.aClockwise;\r\n\r\n\t\tthis.aRotation = source.aRotation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\r\n\tEllipseCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.aX = this.aX;\r\n\t\tdata.aY = this.aY;\r\n\r\n\t\tdata.xRadius = this.xRadius;\r\n\t\tdata.yRadius = this.yRadius;\r\n\r\n\t\tdata.aStartAngle = this.aStartAngle;\r\n\t\tdata.aEndAngle = this.aEndAngle;\r\n\r\n\t\tdata.aClockwise = this.aClockwise;\r\n\r\n\t\tdata.aRotation = this.aRotation;\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tEllipseCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.aX = json.aX;\r\n\t\tthis.aY = json.aY;\r\n\r\n\t\tthis.xRadius = json.xRadius;\r\n\t\tthis.yRadius = json.yRadius;\r\n\r\n\t\tthis.aStartAngle = json.aStartAngle;\r\n\t\tthis.aEndAngle = json.aEndAngle;\r\n\r\n\t\tthis.aClockwise = json.aClockwise;\r\n\r\n\t\tthis.aRotation = json.aRotation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\tEllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\tthis.type = 'ArcCurve';\r\n\r\n\t}\r\n\r\n\tArcCurve.prototype = Object.create( EllipseCurve.prototype );\r\n\tArcCurve.prototype.constructor = ArcCurve;\r\n\r\n\tArcCurve.prototype.isArcCurve = true;\n\n\t/**\r\n\t * @author zz85 https://github.com/zz85\r\n\t *\r\n\t * Centripetal CatmullRom Curve - which is useful for avoiding\r\n\t * cusps and self-intersections in non-uniform catmull rom curves.\r\n\t * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf\r\n\t *\r\n\t * curve.type accepts centripetal(default), chordal and catmullrom\r\n\t * curve.tension is used for catmullrom which defaults to 0.5\r\n\t */\r\n\r\n\r\n\t/*\r\n\tBased on an optimized c++ solution in\r\n\t - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/\r\n\t - http://ideone.com/NoEbVM\r\n\r\n\tThis CubicPoly class could be used for reusing some variables and calculations,\r\n\tbut for three.js curve use, it could be possible inlined and flatten into a single function call\r\n\twhich can be placed in CurveUtils.\r\n\t*/\r\n\r\n\tfunction CubicPoly() {\r\n\r\n\t\tvar c0 = 0, c1 = 0, c2 = 0, c3 = 0;\r\n\r\n\t\t/*\r\n\t\t * Compute coefficients for a cubic polynomial\r\n\t\t * p(s) = c0 + c1*s + c2*s^2 + c3*s^3\r\n\t\t * such that\r\n\t\t * p(0) = x0, p(1) = x1\r\n\t\t * and\r\n\t\t * p'(0) = t0, p'(1) = t1.\r\n\t\t */\r\n\t\tfunction init( x0, x1, t0, t1 ) {\r\n\r\n\t\t\tc0 = x0;\r\n\t\t\tc1 = t0;\r\n\t\t\tc2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;\r\n\t\t\tc3 = 2 * x0 - 2 * x1 + t0 + t1;\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tinitCatmullRom: function ( x0, x1, x2, x3, tension ) {\r\n\r\n\t\t\t\tinit( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );\r\n\r\n\t\t\t},\r\n\r\n\t\t\tinitNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {\r\n\r\n\t\t\t\t// compute tangents when parameterized in [t1,t2]\r\n\t\t\t\tvar t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;\r\n\t\t\t\tvar t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;\r\n\r\n\t\t\t\t// rescale tangents for parametrization in [0,1]\r\n\t\t\t\tt1 *= dt1;\r\n\t\t\t\tt2 *= dt1;\r\n\r\n\t\t\t\tinit( x1, x2, t1, t2 );\r\n\r\n\t\t\t},\r\n\r\n\t\t\tcalc: function ( t ) {\r\n\r\n\t\t\t\tvar t2 = t * t;\r\n\t\t\t\tvar t3 = t2 * t;\r\n\t\t\t\treturn c0 + c1 * t + c2 * t2 + c3 * t3;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tvar tmp = new Vector3();\r\n\tvar px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();\r\n\r\n\tfunction CatmullRomCurve3( points, closed, curveType, tension ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CatmullRomCurve3';\r\n\r\n\t\tthis.points = points || [];\r\n\t\tthis.closed = closed || false;\r\n\t\tthis.curveType = curveType || 'centripetal';\r\n\t\tthis.tension = tension || 0.5;\r\n\r\n\t}\r\n\r\n\tCatmullRomCurve3.prototype = Object.create( Curve.prototype );\r\n\tCatmullRomCurve3.prototype.constructor = CatmullRomCurve3;\r\n\r\n\tCatmullRomCurve3.prototype.isCatmullRomCurve3 = true;\r\n\r\n\tCatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar points = this.points;\r\n\t\tvar l = points.length;\r\n\r\n\t\tvar p = ( l - ( this.closed ? 0 : 1 ) ) * t;\r\n\t\tvar intPoint = Math.floor( p );\r\n\t\tvar weight = p - intPoint;\r\n\r\n\t\tif ( this.closed ) {\r\n\r\n\t\t\tintPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;\r\n\r\n\t\t} else if ( weight === 0 && intPoint === l - 1 ) {\r\n\r\n\t\t\tintPoint = l - 2;\r\n\t\t\tweight = 1;\r\n\r\n\t\t}\r\n\r\n\t\tvar p0, p1, p2, p3; // 4 points\r\n\r\n\t\tif ( this.closed || intPoint > 0 ) {\r\n\r\n\t\t\tp0 = points[ ( intPoint - 1 ) % l ];\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// extrapolate first point\r\n\t\t\ttmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );\r\n\t\t\tp0 = tmp;\r\n\r\n\t\t}\r\n\r\n\t\tp1 = points[ intPoint % l ];\r\n\t\tp2 = points[ ( intPoint + 1 ) % l ];\r\n\r\n\t\tif ( this.closed || intPoint + 2 < l ) {\r\n\r\n\t\t\tp3 = points[ ( intPoint + 2 ) % l ];\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// extrapolate last point\r\n\t\t\ttmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );\r\n\t\t\tp3 = tmp;\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {\r\n\r\n\t\t\t// init Centripetal / Chordal Catmull-Rom\r\n\t\t\tvar pow = this.curveType === 'chordal' ? 0.5 : 0.25;\r\n\t\t\tvar dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );\r\n\t\t\tvar dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );\r\n\t\t\tvar dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );\r\n\r\n\t\t\t// safety check for repeated points\r\n\t\t\tif ( dt1 < 1e-4 ) { dt1 = 1.0; }\r\n\t\t\tif ( dt0 < 1e-4 ) { dt0 = dt1; }\r\n\t\t\tif ( dt2 < 1e-4 ) { dt2 = dt1; }\r\n\r\n\t\t\tpx.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );\r\n\t\t\tpy.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );\r\n\t\t\tpz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );\r\n\r\n\t\t} else if ( this.curveType === 'catmullrom' ) {\r\n\r\n\t\t\tpx.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );\r\n\t\t\tpy.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );\r\n\t\t\tpz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );\r\n\r\n\t\t}\r\n\r\n\t\tpoint.set(\r\n\t\t\tpx.calc( weight ),\r\n\t\t\tpy.calc( weight ),\r\n\t\t\tpz.calc( weight )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = source.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = source.points[ i ];\r\n\r\n\t\t\tthis.points.push( point.clone() );\r\n\r\n\t\t}\r\n\r\n\t\tthis.closed = source.closed;\r\n\t\tthis.curveType = source.curveType;\r\n\t\tthis.tension = source.tension;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.points = [];\r\n\r\n\t\tfor ( var i = 0, l = this.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = this.points[ i ];\r\n\t\t\tdata.points.push( point.toArray() );\r\n\r\n\t\t}\r\n\r\n\t\tdata.closed = this.closed;\r\n\t\tdata.curveType = this.curveType;\r\n\t\tdata.tension = this.tension;\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = json.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = json.points[ i ];\r\n\t\t\tthis.points.push( new Vector3().fromArray( point ) );\r\n\r\n\t\t}\r\n\r\n\t\tthis.closed = json.closed;\r\n\t\tthis.curveType = json.curveType;\r\n\t\tthis.tension = json.tension;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t * Bezier Curves formulas obtained from\r\n\t * http://en.wikipedia.org/wiki/Bézier_curve\r\n\t */\r\n\r\n\tfunction CatmullRom( t, p0, p1, p2, p3 ) {\r\n\r\n\t\tvar v0 = ( p2 - p0 ) * 0.5;\r\n\t\tvar v1 = ( p3 - p1 ) * 0.5;\r\n\t\tvar t2 = t * t;\r\n\t\tvar t3 = t * t2;\r\n\t\treturn ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction QuadraticBezierP0( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn k * k * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezierP1( t, p ) {\r\n\r\n\t\treturn 2 * ( 1 - t ) * t * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezierP2( t, p ) {\r\n\r\n\t\treturn t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezier( t, p0, p1, p2 ) {\r\n\r\n\t\treturn QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +\r\n\t\t\tQuadraticBezierP2( t, p2 );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction CubicBezierP0( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn k * k * k * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP1( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn 3 * k * k * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP2( t, p ) {\r\n\r\n\t\treturn 3 * ( 1 - t ) * t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP3( t, p ) {\r\n\r\n\t\treturn t * t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezier( t, p0, p1, p2, p3 ) {\r\n\r\n\t\treturn CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +\r\n\t\t\tCubicBezierP3( t, p3 );\r\n\r\n\t}\n\n\tfunction CubicBezierCurve( v0, v1, v2, v3 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CubicBezierCurve';\r\n\r\n\t\tthis.v0 = v0 || new Vector2();\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\t\tthis.v3 = v3 || new Vector2();\r\n\r\n\t}\r\n\r\n\tCubicBezierCurve.prototype = Object.create( Curve.prototype );\r\n\tCubicBezierCurve.prototype.constructor = CubicBezierCurve;\r\n\r\n\tCubicBezierCurve.prototype.isCubicBezierCurve = true;\r\n\r\n\tCubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;\r\n\r\n\t\tpoint.set(\r\n\t\t\tCubicBezier( t, v0.x, v1.x, v2.x, v3.x ),\r\n\t\t\tCubicBezier( t, v0.y, v1.y, v2.y, v3.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\t\tthis.v3.copy( source.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\t\tdata.v3 = this.v3.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\t\tthis.v3.fromArray( json.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction CubicBezierCurve3( v0, v1, v2, v3 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CubicBezierCurve3';\r\n\r\n\t\tthis.v0 = v0 || new Vector3();\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\t\tthis.v3 = v3 || new Vector3();\r\n\r\n\t}\r\n\r\n\tCubicBezierCurve3.prototype = Object.create( Curve.prototype );\r\n\tCubicBezierCurve3.prototype.constructor = CubicBezierCurve3;\r\n\r\n\tCubicBezierCurve3.prototype.isCubicBezierCurve3 = true;\r\n\r\n\tCubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;\r\n\r\n\t\tpoint.set(\r\n\t\t\tCubicBezier( t, v0.x, v1.x, v2.x, v3.x ),\r\n\t\t\tCubicBezier( t, v0.y, v1.y, v2.y, v3.y ),\r\n\t\t\tCubicBezier( t, v0.z, v1.z, v2.z, v3.z )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\t\tthis.v3.copy( source.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\t\tdata.v3 = this.v3.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\t\tthis.v3.fromArray( json.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction LineCurve( v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'LineCurve';\r\n\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\r\n\t}\r\n\r\n\tLineCurve.prototype = Object.create( Curve.prototype );\r\n\tLineCurve.prototype.constructor = LineCurve;\r\n\r\n\tLineCurve.prototype.isLineCurve = true;\r\n\r\n\tLineCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tif ( t === 1 ) {\r\n\r\n\t\t\tpoint.copy( this.v2 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tpoint.copy( this.v2 ).sub( this.v1 );\r\n\t\t\tpoint.multiplyScalar( t ).add( this.v1 );\r\n\r\n\t\t}\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\t// Line curve is linear, so we can overwrite default getPointAt\r\n\r\n\tLineCurve.prototype.getPointAt = function ( u, optionalTarget ) {\r\n\r\n\t\treturn this.getPoint( u, optionalTarget );\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.getTangent = function ( /* t */ ) {\r\n\r\n\t\tvar tangent = this.v2.clone().sub( this.v1 );\r\n\r\n\t\treturn tangent.normalize();\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction LineCurve3( v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'LineCurve3';\r\n\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\r\n\t}\r\n\r\n\tLineCurve3.prototype = Object.create( Curve.prototype );\r\n\tLineCurve3.prototype.constructor = LineCurve3;\r\n\r\n\tLineCurve3.prototype.isLineCurve3 = true;\r\n\r\n\tLineCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tif ( t === 1 ) {\r\n\r\n\t\t\tpoint.copy( this.v2 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tpoint.copy( this.v2 ).sub( this.v1 );\r\n\t\t\tpoint.multiplyScalar( t ).add( this.v1 );\r\n\r\n\t\t}\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\t// Line curve is linear, so we can overwrite default getPointAt\r\n\r\n\tLineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {\r\n\r\n\t\treturn this.getPoint( u, optionalTarget );\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction QuadraticBezierCurve( v0, v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'QuadraticBezierCurve';\r\n\r\n\t\tthis.v0 = v0 || new Vector2();\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\r\n\t}\r\n\r\n\tQuadraticBezierCurve.prototype = Object.create( Curve.prototype );\r\n\tQuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;\r\n\r\n\tQuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;\r\n\r\n\tQuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2;\r\n\r\n\t\tpoint.set(\r\n\t\t\tQuadraticBezier( t, v0.x, v1.x, v2.x ),\r\n\t\t\tQuadraticBezier( t, v0.y, v1.y, v2.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction QuadraticBezierCurve3( v0, v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'QuadraticBezierCurve3';\r\n\r\n\t\tthis.v0 = v0 || new Vector3();\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\r\n\t}\r\n\r\n\tQuadraticBezierCurve3.prototype = Object.create( Curve.prototype );\r\n\tQuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;\r\n\r\n\tQuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;\r\n\r\n\tQuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2;\r\n\r\n\t\tpoint.set(\r\n\t\t\tQuadraticBezier( t, v0.x, v1.x, v2.x ),\r\n\t\t\tQuadraticBezier( t, v0.y, v1.y, v2.y ),\r\n\t\t\tQuadraticBezier( t, v0.z, v1.z, v2.z )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction SplineCurve( points /* array of Vector2 */ ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'SplineCurve';\r\n\r\n\t\tthis.points = points || [];\r\n\r\n\t}\r\n\r\n\tSplineCurve.prototype = Object.create( Curve.prototype );\r\n\tSplineCurve.prototype.constructor = SplineCurve;\r\n\r\n\tSplineCurve.prototype.isSplineCurve = true;\r\n\r\n\tSplineCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar points = this.points;\r\n\t\tvar p = ( points.length - 1 ) * t;\r\n\r\n\t\tvar intPoint = Math.floor( p );\r\n\t\tvar weight = p - intPoint;\r\n\r\n\t\tvar p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];\r\n\t\tvar p1 = points[ intPoint ];\r\n\t\tvar p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];\r\n\t\tvar p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];\r\n\r\n\t\tpoint.set(\r\n\t\t\tCatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),\r\n\t\t\tCatmullRom( weight, p0.y, p1.y, p2.y, p3.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = source.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = source.points[ i ];\r\n\r\n\t\t\tthis.points.push( point.clone() );\r\n\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.points = [];\r\n\r\n\t\tfor ( var i = 0, l = this.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = this.points[ i ];\r\n\t\t\tdata.points.push( point.toArray() );\r\n\r\n\t\t}\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = json.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = json.points[ i ];\r\n\t\t\tthis.points.push( new Vector2().fromArray( point ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\n\n\tvar Curves = /*#__PURE__*/Object.freeze({\n\t\tArcCurve: ArcCurve,\n\t\tCatmullRomCurve3: CatmullRomCurve3,\n\t\tCubicBezierCurve: CubicBezierCurve,\n\t\tCubicBezierCurve3: CubicBezierCurve3,\n\t\tEllipseCurve: EllipseCurve,\n\t\tLineCurve: LineCurve,\n\t\tLineCurve3: LineCurve3,\n\t\tQuadraticBezierCurve: QuadraticBezierCurve,\n\t\tQuadraticBezierCurve3: QuadraticBezierCurve3,\n\t\tSplineCurve: SplineCurve\n\t});\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t **/\r\n\r\n\t/**************************************************************\r\n\t *\tCurved Path - a curve path is simply a array of connected\r\n\t * curves, but retains the api of a curve\r\n\t **************************************************************/\r\n\r\n\tfunction CurvePath() {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CurvePath';\r\n\r\n\t\tthis.curves = [];\r\n\t\tthis.autoClose = false; // Automatically closes the path\r\n\r\n\t}\r\n\r\n\tCurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {\r\n\r\n\t\tconstructor: CurvePath,\r\n\r\n\t\tadd: function ( curve ) {\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t},\r\n\r\n\t\tclosePath: function () {\r\n\r\n\t\t\t// Add a line curve if start and end of lines are not connected\r\n\t\t\tvar startPoint = this.curves[ 0 ].getPoint( 0 );\r\n\t\t\tvar endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );\r\n\r\n\t\t\tif ( ! startPoint.equals( endPoint ) ) {\r\n\r\n\t\t\t\tthis.curves.push( new LineCurve( endPoint, startPoint ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// To get accurate point with reference to\r\n\t\t// entire path distance at time t,\r\n\t\t// following has to be done:\r\n\r\n\t\t// 1. Length of each sub path have to be known\r\n\t\t// 2. Locate and identify type of curve\r\n\t\t// 3. Get t for the curve\r\n\t\t// 4. Return curve.getPointAt(t')\r\n\r\n\t\tgetPoint: function ( t ) {\r\n\r\n\t\t\tvar d = t * this.getLength();\r\n\t\t\tvar curveLengths = this.getCurveLengths();\r\n\t\t\tvar i = 0;\r\n\r\n\t\t\t// To think about boundaries points.\r\n\r\n\t\t\twhile ( i < curveLengths.length ) {\r\n\r\n\t\t\t\tif ( curveLengths[ i ] >= d ) {\r\n\r\n\t\t\t\t\tvar diff = curveLengths[ i ] - d;\r\n\t\t\t\t\tvar curve = this.curves[ i ];\r\n\r\n\t\t\t\t\tvar segmentLength = curve.getLength();\r\n\t\t\t\t\tvar u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;\r\n\r\n\t\t\t\t\treturn curve.getPointAt( u );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ti ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t\t// loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {\r\n\r\n\t\t\t\tpoints.push( points[ 0 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = source.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = source.curves[ i ];\r\n\r\n\t\t\t\tthis.curves.push( curve.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.autoClose = source.autoClose;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.autoClose = this.autoClose;\r\n\t\t\tdata.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = this.curves[ i ];\r\n\t\t\t\tdata.curves.push( curve.toJSON() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.autoClose = json.autoClose;\r\n\t\t\tthis.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = json.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = json.curves[ i ];\r\n\t\t\t\tthis.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Creates free form 2d path using series of points, lines or curves.\r\n\t **/\r\n\r\n\tfunction Path( points ) {\r\n\r\n\t\tCurvePath.call( this );\r\n\r\n\t\tthis.type = 'Path';\r\n\r\n\t\tthis.currentPoint = new Vector2();\r\n\r\n\t\tif ( points ) {\r\n\r\n\t\t\tthis.setFromPoints( points );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tPath.prototype = Object.assign( Object.create( CurvePath.prototype ), {\r\n\r\n\t\tconstructor: Path,\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.moveTo( points[ 0 ].x, points[ 0 ].y );\r\n\r\n\t\t\tfor ( var i = 1, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.lineTo( points[ i ].x, points[ i ].y );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmoveTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlineTo: function ( x, y ) {\r\n\r\n\t\t\tvar curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tquadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {\r\n\r\n\t\t\tvar curve = new QuadraticBezierCurve(\r\n\t\t\t\tthis.currentPoint.clone(),\r\n\t\t\t\tnew Vector2( aCPx, aCPy ),\r\n\t\t\t\tnew Vector2( aX, aY )\r\n\t\t\t);\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tbezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {\r\n\r\n\t\t\tvar curve = new CubicBezierCurve(\r\n\t\t\t\tthis.currentPoint.clone(),\r\n\t\t\t\tnew Vector2( aCP1x, aCP1y ),\r\n\t\t\t\tnew Vector2( aCP2x, aCP2y ),\r\n\t\t\t\tnew Vector2( aX, aY )\r\n\t\t\t);\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsplineThru: function ( pts /*Array of Vector*/ ) {\r\n\r\n\t\t\tvar npts = [ this.currentPoint.clone() ].concat( pts );\r\n\r\n\t\t\tvar curve = new SplineCurve( npts );\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.copy( pts[ pts.length - 1 ] );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\t\tvar x0 = this.currentPoint.x;\r\n\t\t\tvar y0 = this.currentPoint.y;\r\n\r\n\t\t\tthis.absarc( aX + x0, aY + y0, aRadius,\r\n\t\t\t\taStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tabsarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\t\tthis.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\t\tvar x0 = this.currentPoint.x;\r\n\t\t\tvar y0 = this.currentPoint.y;\r\n\r\n\t\t\tthis.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tabsellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\t\tvar curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );\r\n\r\n\t\t\tif ( this.curves.length > 0 ) {\r\n\r\n\t\t\t\t// if a previous curve is present, attempt to join\r\n\t\t\t\tvar firstPoint = curve.getPoint( 0 );\r\n\r\n\t\t\t\tif ( ! firstPoint.equals( this.currentPoint ) ) {\r\n\r\n\t\t\t\t\tthis.lineTo( firstPoint.x, firstPoint.y );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tvar lastPoint = curve.getPoint( 1 );\r\n\t\t\tthis.currentPoint.copy( lastPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tCurvePath.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.currentPoint.copy( source.currentPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = CurvePath.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.currentPoint = this.currentPoint.toArray();\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tCurvePath.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.currentPoint.fromArray( json.currentPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Defines a 2d shape plane using paths.\r\n\t **/\r\n\r\n\t// STEP 1 Create a path.\r\n\t// STEP 2 Turn path into shape.\r\n\t// STEP 3 ExtrudeGeometry takes in Shape/Shapes\r\n\t// STEP 3a - Extract points from each shape, turn to vertices\r\n\t// STEP 3b - Triangulate each shape, add faces.\r\n\r\n\tfunction Shape( points ) {\r\n\r\n\t\tPath.call( this, points );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.type = 'Shape';\r\n\r\n\t\tthis.holes = [];\r\n\r\n\t}\r\n\r\n\tShape.prototype = Object.assign( Object.create( Path.prototype ), {\r\n\r\n\t\tconstructor: Shape,\r\n\r\n\t\tgetPointsHoles: function ( divisions ) {\r\n\r\n\t\t\tvar holesPts = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tholesPts[ i ] = this.holes[ i ].getPoints( divisions );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn holesPts;\r\n\r\n\t\t},\r\n\r\n\t\t// get points of shape and holes (keypoints based on segments parameter)\r\n\r\n\t\textractPoints: function ( divisions ) {\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tshape: this.getPoints( divisions ),\r\n\t\t\t\tholes: this.getPointsHoles( divisions )\r\n\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tPath.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = source.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = source.holes[ i ];\r\n\r\n\t\t\t\tthis.holes.push( hole.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = Path.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = this.holes[ i ];\r\n\t\t\t\tdata.holes.push( hole.toJSON() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tPath.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.uuid = json.uuid;\r\n\t\t\tthis.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = json.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = json.holes[ i ];\r\n\t\t\t\tthis.holes.push( new Path().fromJSON( hole ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Light( color, intensity ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Light';\r\n\r\n\t\tthis.color = new Color( color );\r\n\t\tthis.intensity = intensity !== undefined ? intensity : 1;\r\n\r\n\t\tthis.receiveShadow = undefined;\r\n\r\n\t}\r\n\r\n\tLight.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Light,\r\n\r\n\t\tisLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.color.copy( source.color );\r\n\t\t\tthis.intensity = source.intensity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.color = this.color.getHex();\r\n\t\t\tdata.object.intensity = this.intensity;\r\n\r\n\t\t\tif ( this.groundColor !== undefined ) { data.object.groundColor = this.groundColor.getHex(); }\r\n\r\n\t\t\tif ( this.distance !== undefined ) { data.object.distance = this.distance; }\r\n\t\t\tif ( this.angle !== undefined ) { data.object.angle = this.angle; }\r\n\t\t\tif ( this.decay !== undefined ) { data.object.decay = this.decay; }\r\n\t\t\tif ( this.penumbra !== undefined ) { data.object.penumbra = this.penumbra; }\r\n\r\n\t\t\tif ( this.shadow !== undefined ) { data.object.shadow = this.shadow.toJSON(); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction HemisphereLight( skyColor, groundColor, intensity ) {\r\n\r\n\t\tLight.call( this, skyColor, intensity );\r\n\r\n\t\tthis.type = 'HemisphereLight';\r\n\r\n\t\tthis.castShadow = undefined;\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.groundColor = new Color( groundColor );\r\n\r\n\t}\r\n\r\n\tHemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: HemisphereLight,\r\n\r\n\t\tisHemisphereLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.groundColor.copy( source.groundColor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction LightShadow( camera ) {\r\n\r\n\t\tthis.camera = camera;\r\n\r\n\t\tthis.bias = 0;\r\n\t\tthis.radius = 1;\r\n\r\n\t\tthis.mapSize = new Vector2( 512, 512 );\r\n\r\n\t\tthis.map = null;\r\n\t\tthis.mapPass = null;\r\n\t\tthis.matrix = new Matrix4();\r\n\r\n\t\tthis._frustum = new Frustum();\r\n\t\tthis._frameExtents = new Vector2( 1, 1 );\r\n\r\n\t\tthis._viewportCount = 1;\r\n\r\n\t\tthis._viewports = [\r\n\r\n\t\t\tnew Vector4( 0, 0, 1, 1 )\r\n\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tObject.assign( LightShadow.prototype, {\r\n\r\n\t\t_projScreenMatrix: new Matrix4(),\r\n\r\n\t\t_lightPositionWorld: new Vector3(),\r\n\r\n\t\t_lookTarget: new Vector3(),\r\n\r\n\t\tgetViewportCount: function () {\r\n\r\n\t\t\treturn this._viewportCount;\r\n\r\n\t\t},\r\n\r\n\t\tgetFrustum: function () {\r\n\r\n\t\t\treturn this._frustum;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tvar shadowCamera = this.camera,\r\n\t\t\t\tshadowMatrix = this.matrix,\r\n\t\t\t\tprojScreenMatrix = this._projScreenMatrix,\r\n\t\t\t\tlookTarget = this._lookTarget,\r\n\t\t\t\tlightPositionWorld = this._lightPositionWorld;\r\n\r\n\t\t\tlightPositionWorld.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\tshadowCamera.position.copy( lightPositionWorld );\r\n\r\n\t\t\tlookTarget.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\tshadowCamera.lookAt( lookTarget );\r\n\t\t\tshadowCamera.updateMatrixWorld();\r\n\r\n\t\t\tprojScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );\r\n\t\t\tthis._frustum.setFromMatrix( projScreenMatrix );\r\n\r\n\t\t\tshadowMatrix.set(\r\n\t\t\t\t0.5, 0.0, 0.0, 0.5,\r\n\t\t\t\t0.0, 0.5, 0.0, 0.5,\r\n\t\t\t\t0.0, 0.0, 0.5, 0.5,\r\n\t\t\t\t0.0, 0.0, 0.0, 1.0\r\n\t\t\t);\r\n\r\n\t\t\tshadowMatrix.multiply( shadowCamera.projectionMatrix );\r\n\t\t\tshadowMatrix.multiply( shadowCamera.matrixWorldInverse );\r\n\r\n\t\t},\r\n\r\n\t\tgetViewport: function ( viewportIndex ) {\r\n\r\n\t\t\treturn this._viewports[ viewportIndex ];\r\n\r\n\t\t},\r\n\r\n\t\tgetFrameExtents: function () {\r\n\r\n\t\t\treturn this._frameExtents;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.camera = source.camera.clone();\r\n\r\n\t\t\tthis.bias = source.bias;\r\n\t\t\tthis.radius = source.radius;\r\n\r\n\t\t\tthis.mapSize.copy( source.mapSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar object = {};\r\n\r\n\t\t\tif ( this.bias !== 0 ) { object.bias = this.bias; }\r\n\t\t\tif ( this.radius !== 1 ) { object.radius = this.radius; }\r\n\t\t\tif ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) { object.mapSize = this.mapSize.toArray(); }\r\n\r\n\t\t\tobject.camera = this.camera.toJSON( false ).object;\r\n\t\t\tdelete object.camera.matrix;\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction SpotLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );\r\n\r\n\t}\r\n\r\n\tSpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: SpotLightShadow,\r\n\r\n\t\tisSpotLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tvar camera = this.camera;\r\n\r\n\t\t\tvar fov = _Math.RAD2DEG * 2 * light.angle;\r\n\t\t\tvar aspect = this.mapSize.width / this.mapSize.height;\r\n\t\t\tvar far = light.distance || camera.far;\r\n\r\n\t\t\tif ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {\r\n\r\n\t\t\t\tcamera.fov = fov;\r\n\t\t\t\tcamera.aspect = aspect;\r\n\t\t\t\tcamera.far = far;\r\n\t\t\t\tcamera.updateProjectionMatrix();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tLightShadow.prototype.updateMatrices.call( this, light );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction SpotLight( color, intensity, distance, angle, penumbra, decay ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'SpotLight';\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.target = new Object3D();\r\n\r\n\t\tObject.defineProperty( this, 'power', {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\treturn this.intensity * Math.PI;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( power ) {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\tthis.intensity = power / Math.PI;\r\n\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.distance = ( distance !== undefined ) ? distance : 0;\r\n\t\tthis.angle = ( angle !== undefined ) ? angle : Math.PI / 3;\r\n\t\tthis.penumbra = ( penumbra !== undefined ) ? penumbra : 0;\r\n\t\tthis.decay = ( decay !== undefined ) ? decay : 1;\t// for physically correct lights, should be 2.\r\n\r\n\t\tthis.shadow = new SpotLightShadow();\r\n\r\n\t}\r\n\r\n\tSpotLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: SpotLight,\r\n\r\n\t\tisSpotLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.distance = source.distance;\r\n\t\t\tthis.angle = source.angle;\r\n\t\t\tthis.penumbra = source.penumbra;\r\n\t\t\tthis.decay = source.decay;\r\n\r\n\t\t\tthis.target = source.target.clone();\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tfunction PointLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );\r\n\r\n\t\tthis._frameExtents = new Vector2( 4, 2 );\r\n\r\n\t\tthis._viewportCount = 6;\r\n\r\n\t\tthis._viewports = [\r\n\t\t\t// These viewports map a cube-map onto a 2D texture with the\r\n\t\t\t// following orientation:\r\n\t\t\t//\r\n\t\t\t// xzXZ\r\n\t\t\t// y Y\r\n\t\t\t//\r\n\t\t\t// X - Positive x direction\r\n\t\t\t// x - Negative x direction\r\n\t\t\t// Y - Positive y direction\r\n\t\t\t// y - Negative y direction\r\n\t\t\t// Z - Positive z direction\r\n\t\t\t// z - Negative z direction\r\n\r\n\t\t\t// positive X\r\n\t\t\tnew Vector4( 2, 1, 1, 1 ),\r\n\t\t\t// negative X\r\n\t\t\tnew Vector4( 0, 1, 1, 1 ),\r\n\t\t\t// positive Z\r\n\t\t\tnew Vector4( 3, 1, 1, 1 ),\r\n\t\t\t// negative Z\r\n\t\t\tnew Vector4( 1, 1, 1, 1 ),\r\n\t\t\t// positive Y\r\n\t\t\tnew Vector4( 3, 0, 1, 1 ),\r\n\t\t\t// negative Y\r\n\t\t\tnew Vector4( 1, 0, 1, 1 )\r\n\t\t];\r\n\r\n\t\tthis._cubeDirections = [\r\n\t\t\tnew Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),\r\n\t\t\tnew Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )\r\n\t\t];\r\n\r\n\t\tthis._cubeUps = [\r\n\t\t\tnew Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),\r\n\t\t\tnew Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),\tnew Vector3( 0, 0, - 1 )\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tPointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: PointLightShadow,\r\n\r\n\t\tisPointLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light, viewportIndex ) {\r\n\r\n\t\t\tif ( viewportIndex === undefined ) { viewportIndex = 0; }\r\n\r\n\t\t\tvar camera = this.camera,\r\n\t\t\t\tshadowMatrix = this.matrix,\r\n\t\t\t\tlightPositionWorld = this._lightPositionWorld,\r\n\t\t\t\tlookTarget = this._lookTarget,\r\n\t\t\t\tprojScreenMatrix = this._projScreenMatrix;\r\n\r\n\t\t\tlightPositionWorld.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\tcamera.position.copy( lightPositionWorld );\r\n\r\n\t\t\tlookTarget.copy( camera.position );\r\n\t\t\tlookTarget.add( this._cubeDirections[ viewportIndex ] );\r\n\t\t\tcamera.up.copy( this._cubeUps[ viewportIndex ] );\r\n\t\t\tcamera.lookAt( lookTarget );\r\n\t\t\tcamera.updateMatrixWorld();\r\n\r\n\t\t\tshadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );\r\n\r\n\t\t\tprojScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\r\n\t\t\tthis._frustum.setFromMatrix( projScreenMatrix );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction PointLight( color, intensity, distance, decay ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'PointLight';\r\n\r\n\t\tObject.defineProperty( this, 'power', {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\treturn this.intensity * 4 * Math.PI;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( power ) {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\tthis.intensity = power / ( 4 * Math.PI );\r\n\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.distance = ( distance !== undefined ) ? distance : 0;\r\n\t\tthis.decay = ( decay !== undefined ) ? decay : 1;\t// for physically correct lights, should be 2.\r\n\r\n\t\tthis.shadow = new PointLightShadow();\r\n\r\n\t}\r\n\r\n\tPointLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: PointLight,\r\n\r\n\t\tisPointLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.distance = source.distance;\r\n\t\t\tthis.decay = source.decay;\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author arose / http://github.com/arose\r\n\t */\r\n\r\n\tfunction OrthographicCamera( left, right, top, bottom, near, far ) {\r\n\r\n\t\tCamera.call( this );\r\n\r\n\t\tthis.type = 'OrthographicCamera';\r\n\r\n\t\tthis.zoom = 1;\r\n\t\tthis.view = null;\r\n\r\n\t\tthis.left = ( left !== undefined ) ? left : - 1;\r\n\t\tthis.right = ( right !== undefined ) ? right : 1;\r\n\t\tthis.top = ( top !== undefined ) ? top : 1;\r\n\t\tthis.bottom = ( bottom !== undefined ) ? bottom : - 1;\r\n\r\n\t\tthis.near = ( near !== undefined ) ? near : 0.1;\r\n\t\tthis.far = ( far !== undefined ) ? far : 2000;\r\n\r\n\t\tthis.updateProjectionMatrix();\r\n\r\n\t}\r\n\r\n\tOrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\r\n\r\n\t\tconstructor: OrthographicCamera,\r\n\r\n\t\tisOrthographicCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tCamera.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.left = source.left;\r\n\t\t\tthis.right = source.right;\r\n\t\t\tthis.top = source.top;\r\n\t\t\tthis.bottom = source.bottom;\r\n\t\t\tthis.near = source.near;\r\n\t\t\tthis.far = source.far;\r\n\r\n\t\t\tthis.zoom = source.zoom;\r\n\t\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\r\n\r\n\t\t\tif ( this.view === null ) {\r\n\r\n\t\t\t\tthis.view = {\r\n\t\t\t\t\tenabled: true,\r\n\t\t\t\t\tfullWidth: 1,\r\n\t\t\t\t\tfullHeight: 1,\r\n\t\t\t\t\toffsetX: 0,\r\n\t\t\t\t\toffsetY: 0,\r\n\t\t\t\t\twidth: 1,\r\n\t\t\t\t\theight: 1\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.view.enabled = true;\r\n\t\t\tthis.view.fullWidth = fullWidth;\r\n\t\t\tthis.view.fullHeight = fullHeight;\r\n\t\t\tthis.view.offsetX = x;\r\n\t\t\tthis.view.offsetY = y;\r\n\t\t\tthis.view.width = width;\r\n\t\t\tthis.view.height = height;\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tclearViewOffset: function () {\r\n\r\n\t\t\tif ( this.view !== null ) {\r\n\r\n\t\t\t\tthis.view.enabled = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tupdateProjectionMatrix: function () {\r\n\r\n\t\t\tvar dx = ( this.right - this.left ) / ( 2 * this.zoom );\r\n\t\t\tvar dy = ( this.top - this.bottom ) / ( 2 * this.zoom );\r\n\t\t\tvar cx = ( this.right + this.left ) / 2;\r\n\t\t\tvar cy = ( this.top + this.bottom ) / 2;\r\n\r\n\t\t\tvar left = cx - dx;\r\n\t\t\tvar right = cx + dx;\r\n\t\t\tvar top = cy + dy;\r\n\t\t\tvar bottom = cy - dy;\r\n\r\n\t\t\tif ( this.view !== null && this.view.enabled ) {\r\n\r\n\t\t\t\tvar zoomW = this.zoom / ( this.view.width / this.view.fullWidth );\r\n\t\t\t\tvar zoomH = this.zoom / ( this.view.height / this.view.fullHeight );\r\n\t\t\t\tvar scaleW = ( this.right - this.left ) / this.view.width;\r\n\t\t\t\tvar scaleH = ( this.top - this.bottom ) / this.view.height;\r\n\r\n\t\t\t\tleft += scaleW * ( this.view.offsetX / zoomW );\r\n\t\t\t\tright = left + scaleW * ( this.view.width / zoomW );\r\n\t\t\t\ttop -= scaleH * ( this.view.offsetY / zoomH );\r\n\t\t\t\tbottom = top - scaleH * ( this.view.height / zoomH );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );\r\n\r\n\t\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.zoom = this.zoom;\r\n\t\t\tdata.object.left = this.left;\r\n\t\t\tdata.object.right = this.right;\r\n\t\t\tdata.object.top = this.top;\r\n\t\t\tdata.object.bottom = this.bottom;\r\n\t\t\tdata.object.near = this.near;\r\n\t\t\tdata.object.far = this.far;\r\n\r\n\t\t\tif ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction DirectionalLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );\r\n\r\n\t}\r\n\r\n\tDirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: DirectionalLightShadow,\r\n\r\n\t\tisDirectionalLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tLightShadow.prototype.updateMatrices.call( this, light );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction DirectionalLight( color, intensity ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'DirectionalLight';\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.target = new Object3D();\r\n\r\n\t\tthis.shadow = new DirectionalLightShadow();\r\n\r\n\t}\r\n\r\n\tDirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: DirectionalLight,\r\n\r\n\t\tisDirectionalLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.target = source.target.clone();\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AmbientLight( color, intensity ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'AmbientLight';\r\n\r\n\t\tthis.castShadow = undefined;\r\n\r\n\t}\r\n\r\n\tAmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: AmbientLight,\r\n\r\n\t\tisAmbientLight: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t */\r\n\r\n\tfunction RectAreaLight( color, intensity, width, height ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'RectAreaLight';\r\n\r\n\t\tthis.width = ( width !== undefined ) ? width : 10;\r\n\t\tthis.height = ( height !== undefined ) ? height : 10;\r\n\r\n\t}\r\n\r\n\tRectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: RectAreaLight,\r\n\r\n\t\tisRectAreaLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.width = source.width;\r\n\t\t\tthis.height = source.height;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Light.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.width = this.width;\r\n\t\t\tdata.object.height = this.height;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction MaterialLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t\tthis.textures = {};\r\n\r\n\t}\r\n\r\n\tMaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: MaterialLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar textures = this.textures;\r\n\r\n\t\t\tfunction getTexture( name ) {\r\n\r\n\t\t\t\tif ( textures[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.MaterialLoader: Undefined texture', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn textures[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar material = new Materials[ json.type ]();\r\n\r\n\t\t\tif ( json.uuid !== undefined ) { material.uuid = json.uuid; }\r\n\t\t\tif ( json.name !== undefined ) { material.name = json.name; }\r\n\t\t\tif ( json.color !== undefined ) { material.color.setHex( json.color ); }\r\n\t\t\tif ( json.roughness !== undefined ) { material.roughness = json.roughness; }\r\n\t\t\tif ( json.metalness !== undefined ) { material.metalness = json.metalness; }\r\n\t\t\tif ( json.sheen !== undefined ) { material.sheen = new Color().setHex( json.sheen ); }\r\n\t\t\tif ( json.emissive !== undefined ) { material.emissive.setHex( json.emissive ); }\r\n\t\t\tif ( json.specular !== undefined ) { material.specular.setHex( json.specular ); }\r\n\t\t\tif ( json.shininess !== undefined ) { material.shininess = json.shininess; }\r\n\t\t\tif ( json.clearcoat !== undefined ) { material.clearcoat = json.clearcoat; }\r\n\t\t\tif ( json.clearcoatRoughness !== undefined ) { material.clearcoatRoughness = json.clearcoatRoughness; }\r\n\t\t\tif ( json.vertexColors !== undefined ) { material.vertexColors = json.vertexColors; }\r\n\t\t\tif ( json.fog !== undefined ) { material.fog = json.fog; }\r\n\t\t\tif ( json.flatShading !== undefined ) { material.flatShading = json.flatShading; }\r\n\t\t\tif ( json.blending !== undefined ) { material.blending = json.blending; }\r\n\t\t\tif ( json.combine !== undefined ) { material.combine = json.combine; }\r\n\t\t\tif ( json.side !== undefined ) { material.side = json.side; }\r\n\t\t\tif ( json.opacity !== undefined ) { material.opacity = json.opacity; }\r\n\t\t\tif ( json.transparent !== undefined ) { material.transparent = json.transparent; }\r\n\t\t\tif ( json.alphaTest !== undefined ) { material.alphaTest = json.alphaTest; }\r\n\t\t\tif ( json.depthTest !== undefined ) { material.depthTest = json.depthTest; }\r\n\t\t\tif ( json.depthWrite !== undefined ) { material.depthWrite = json.depthWrite; }\r\n\t\t\tif ( json.colorWrite !== undefined ) { material.colorWrite = json.colorWrite; }\r\n\r\n\t\t\tif ( json.stencilWrite !== undefined ) { material.stencilWrite = json.stencilWrite; }\r\n\t\t\tif ( json.stencilWriteMask !== undefined ) { material.stencilWriteMask = json.stencilWriteMask; }\r\n\t\t\tif ( json.stencilFunc !== undefined ) { material.stencilFunc = json.stencilFunc; }\r\n\t\t\tif ( json.stencilRef !== undefined ) { material.stencilRef = json.stencilRef; }\r\n\t\t\tif ( json.stencilFuncMask !== undefined ) { material.stencilFuncMask = json.stencilFuncMask; }\r\n\t\t\tif ( json.stencilFail !== undefined ) { material.stencilFail = json.stencilFail; }\r\n\t\t\tif ( json.stencilZFail !== undefined ) { material.stencilZFail = json.stencilZFail; }\r\n\t\t\tif ( json.stencilZPass !== undefined ) { material.stencilZPass = json.stencilZPass; }\r\n\r\n\t\t\tif ( json.wireframe !== undefined ) { material.wireframe = json.wireframe; }\r\n\t\t\tif ( json.wireframeLinewidth !== undefined ) { material.wireframeLinewidth = json.wireframeLinewidth; }\r\n\t\t\tif ( json.wireframeLinecap !== undefined ) { material.wireframeLinecap = json.wireframeLinecap; }\r\n\t\t\tif ( json.wireframeLinejoin !== undefined ) { material.wireframeLinejoin = json.wireframeLinejoin; }\r\n\r\n\t\t\tif ( json.rotation !== undefined ) { material.rotation = json.rotation; }\r\n\r\n\t\t\tif ( json.linewidth !== 1 ) { material.linewidth = json.linewidth; }\r\n\t\t\tif ( json.dashSize !== undefined ) { material.dashSize = json.dashSize; }\r\n\t\t\tif ( json.gapSize !== undefined ) { material.gapSize = json.gapSize; }\r\n\t\t\tif ( json.scale !== undefined ) { material.scale = json.scale; }\r\n\r\n\t\t\tif ( json.polygonOffset !== undefined ) { material.polygonOffset = json.polygonOffset; }\r\n\t\t\tif ( json.polygonOffsetFactor !== undefined ) { material.polygonOffsetFactor = json.polygonOffsetFactor; }\r\n\t\t\tif ( json.polygonOffsetUnits !== undefined ) { material.polygonOffsetUnits = json.polygonOffsetUnits; }\r\n\r\n\t\t\tif ( json.skinning !== undefined ) { material.skinning = json.skinning; }\r\n\t\t\tif ( json.morphTargets !== undefined ) { material.morphTargets = json.morphTargets; }\r\n\t\t\tif ( json.morphNormals !== undefined ) { material.morphNormals = json.morphNormals; }\r\n\t\t\tif ( json.dithering !== undefined ) { material.dithering = json.dithering; }\r\n\r\n\t\t\tif ( json.visible !== undefined ) { material.visible = json.visible; }\r\n\r\n\t\t\tif ( json.toneMapped !== undefined ) { material.toneMapped = json.toneMapped; }\r\n\r\n\t\t\tif ( json.userData !== undefined ) { material.userData = json.userData; }\r\n\r\n\t\t\t// Shader Material\r\n\r\n\t\t\tif ( json.uniforms !== undefined ) {\r\n\r\n\t\t\t\tfor ( var name in json.uniforms ) {\r\n\r\n\t\t\t\t\tvar uniform = json.uniforms[ name ];\r\n\r\n\t\t\t\t\tmaterial.uniforms[ name ] = {};\r\n\r\n\t\t\t\t\tswitch ( uniform.type ) {\r\n\r\n\t\t\t\t\t\tcase 't':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = getTexture( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'c':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Color().setHex( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v2':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector2().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v3':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector3().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v4':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector4().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'm3':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );\r\n\r\n\t\t\t\t\t\tcase 'm4':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = uniform.value;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.defines !== undefined ) { material.defines = json.defines; }\r\n\t\t\tif ( json.vertexShader !== undefined ) { material.vertexShader = json.vertexShader; }\r\n\t\t\tif ( json.fragmentShader !== undefined ) { material.fragmentShader = json.fragmentShader; }\r\n\r\n\t\t\tif ( json.extensions !== undefined ) {\r\n\r\n\t\t\t\tfor ( var key in json.extensions ) {\r\n\r\n\t\t\t\t\tmaterial.extensions[ key ] = json.extensions[ key ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Deprecated\r\n\r\n\t\t\tif ( json.shading !== undefined ) { material.flatShading = json.shading === 1; } // THREE.FlatShading\r\n\r\n\t\t\t// for PointsMaterial\r\n\r\n\t\t\tif ( json.size !== undefined ) { material.size = json.size; }\r\n\t\t\tif ( json.sizeAttenuation !== undefined ) { material.sizeAttenuation = json.sizeAttenuation; }\r\n\r\n\t\t\t// maps\r\n\r\n\t\t\tif ( json.map !== undefined ) { material.map = getTexture( json.map ); }\r\n\t\t\tif ( json.matcap !== undefined ) { material.matcap = getTexture( json.matcap ); }\r\n\r\n\t\t\tif ( json.alphaMap !== undefined ) {\r\n\r\n\t\t\t\tmaterial.alphaMap = getTexture( json.alphaMap );\r\n\t\t\t\tmaterial.transparent = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.bumpMap !== undefined ) { material.bumpMap = getTexture( json.bumpMap ); }\r\n\t\t\tif ( json.bumpScale !== undefined ) { material.bumpScale = json.bumpScale; }\r\n\r\n\t\t\tif ( json.normalMap !== undefined ) { material.normalMap = getTexture( json.normalMap ); }\r\n\t\t\tif ( json.normalMapType !== undefined ) { material.normalMapType = json.normalMapType; }\r\n\t\t\tif ( json.normalScale !== undefined ) {\r\n\r\n\t\t\t\tvar normalScale = json.normalScale;\r\n\r\n\t\t\t\tif ( Array.isArray( normalScale ) === false ) {\r\n\r\n\t\t\t\t\t// Blender exporter used to export a scalar. See #7459\r\n\r\n\t\t\t\t\tnormalScale = [ normalScale, normalScale ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmaterial.normalScale = new Vector2().fromArray( normalScale );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.displacementMap !== undefined ) { material.displacementMap = getTexture( json.displacementMap ); }\r\n\t\t\tif ( json.displacementScale !== undefined ) { material.displacementScale = json.displacementScale; }\r\n\t\t\tif ( json.displacementBias !== undefined ) { material.displacementBias = json.displacementBias; }\r\n\r\n\t\t\tif ( json.roughnessMap !== undefined ) { material.roughnessMap = getTexture( json.roughnessMap ); }\r\n\t\t\tif ( json.metalnessMap !== undefined ) { material.metalnessMap = getTexture( json.metalnessMap ); }\r\n\r\n\t\t\tif ( json.emissiveMap !== undefined ) { material.emissiveMap = getTexture( json.emissiveMap ); }\r\n\t\t\tif ( json.emissiveIntensity !== undefined ) { material.emissiveIntensity = json.emissiveIntensity; }\r\n\r\n\t\t\tif ( json.specularMap !== undefined ) { material.specularMap = getTexture( json.specularMap ); }\r\n\r\n\t\t\tif ( json.envMap !== undefined ) { material.envMap = getTexture( json.envMap ); }\r\n\t\t\tif ( json.envMapIntensity !== undefined ) { material.envMapIntensity = json.envMapIntensity; }\r\n\r\n\t\t\tif ( json.reflectivity !== undefined ) { material.reflectivity = json.reflectivity; }\r\n\t\t\tif ( json.refractionRatio !== undefined ) { material.refractionRatio = json.refractionRatio; }\r\n\r\n\t\t\tif ( json.lightMap !== undefined ) { material.lightMap = getTexture( json.lightMap ); }\r\n\t\t\tif ( json.lightMapIntensity !== undefined ) { material.lightMapIntensity = json.lightMapIntensity; }\r\n\r\n\t\t\tif ( json.aoMap !== undefined ) { material.aoMap = getTexture( json.aoMap ); }\r\n\t\t\tif ( json.aoMapIntensity !== undefined ) { material.aoMapIntensity = json.aoMapIntensity; }\r\n\r\n\t\t\tif ( json.gradientMap !== undefined ) { material.gradientMap = getTexture( json.gradientMap ); }\r\n\r\n\t\t\tif ( json.clearcoatNormalMap !== undefined ) { material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); }\r\n\t\t\tif ( json.clearcoatNormalScale !== undefined ) { material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); }\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t},\r\n\r\n\t\tsetTextures: function ( value ) {\r\n\r\n\t\t\tthis.textures = value;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Don McCurdy / https://www.donmccurdy.com\r\n\t */\r\n\r\n\tvar LoaderUtils = {\r\n\r\n\t\tdecodeText: function ( array ) {\r\n\r\n\t\t\tif ( typeof TextDecoder !== 'undefined' ) {\r\n\r\n\t\t\t\treturn new TextDecoder().decode( array );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Avoid the String.fromCharCode.apply(null, array) shortcut, which\r\n\t\t\t// throws a \"maximum call stack size exceeded\" error for large arrays.\r\n\r\n\t\t\tvar s = '';\r\n\r\n\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// Implicitly assumes little-endian.\r\n\t\t\t\ts += String.fromCharCode( array[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\t// merges multi-byte utf-8 characters.\r\n\r\n\t\t\t\treturn decodeURIComponent( escape( s ) );\r\n\r\n\t\t\t} catch ( e ) { // see #16358\r\n\r\n\t\t\t\treturn s;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\textractUrlBase: function ( url ) {\r\n\r\n\t\t\tvar index = url.lastIndexOf( '/' );\r\n\r\n\t\t\tif ( index === - 1 ) { return './'; }\r\n\r\n\t\t\treturn url.substr( 0, index + 1 );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedBufferGeometry() {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'InstancedBufferGeometry';\r\n\t\tthis.maxInstancedCount = undefined;\r\n\r\n\t}\r\n\r\n\tInstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {\r\n\r\n\t\tconstructor: InstancedBufferGeometry,\r\n\r\n\t\tisInstancedBufferGeometry: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tBufferGeometry.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.maxInstancedCount = source.maxInstancedCount;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.maxInstancedCount = this.maxInstancedCount;\r\n\r\n\t\t\tdata.isInstancedBufferGeometry = true;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {\r\n\r\n\t\tif ( typeof ( normalized ) === 'number' ) {\r\n\r\n\t\t\tmeshPerAttribute = normalized;\r\n\r\n\t\t\tnormalized = false;\r\n\r\n\t\t\tconsole.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );\r\n\r\n\t\t}\r\n\r\n\t\tBufferAttribute.call( this, array, itemSize, normalized );\r\n\r\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\r\n\r\n\t}\r\n\r\n\tInstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {\r\n\r\n\t\tconstructor: InstancedBufferAttribute,\r\n\r\n\t\tisInstancedBufferAttribute: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tBufferAttribute.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ()\t{\r\n\r\n\t\t\tvar data = BufferAttribute.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.meshPerAttribute = this.meshPerAttribute;\r\n\r\n\t\t\tdata.isInstancedBufferAttribute = true;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction BufferGeometryLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tBufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: BufferGeometryLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();\r\n\r\n\t\t\tvar index = json.data.index;\r\n\r\n\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\tvar typedArray = new TYPED_ARRAYS[ index.type ]( index.array );\r\n\t\t\t\tgeometry.setIndex( new BufferAttribute( typedArray, 1 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = json.data.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ key ];\r\n\t\t\t\tvar typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );\r\n\t\t\t\tvar bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;\r\n\t\t\t\tvar bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );\r\n\t\t\t\tif ( attribute.name !== undefined ) { bufferAttribute.name = attribute.name; }\r\n\t\t\t\tgeometry.setAttribute( key, bufferAttribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphAttributes = json.data.morphAttributes;\r\n\r\n\t\t\tif ( morphAttributes ) {\r\n\r\n\t\t\t\tfor ( var key in morphAttributes ) {\r\n\r\n\t\t\t\t\tvar attributeArray = morphAttributes[ key ];\r\n\r\n\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar attribute = attributeArray[ i ];\r\n\t\t\t\t\t\tvar typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );\r\n\r\n\t\t\t\t\t\tvar bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );\r\n\t\t\t\t\t\tif ( attribute.name !== undefined ) { bufferAttribute.name = attribute.name; }\r\n\t\t\t\t\t\tarray.push( bufferAttribute );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.morphAttributes[ key ] = array;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphTargetsRelative = json.data.morphTargetsRelative;\r\n\r\n\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\tgeometry.morphTargetsRelative = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = json.data.groups || json.data.drawcalls || json.data.offsets;\r\n\r\n\t\t\tif ( groups !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, n = groups.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar group = groups[ i ];\r\n\r\n\t\t\t\t\tgeometry.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundingSphere = json.data.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== undefined ) {\r\n\r\n\t\t\t\tvar center = new Vector3();\r\n\r\n\t\t\t\tif ( boundingSphere.center !== undefined ) {\r\n\r\n\t\t\t\t\tcenter.fromArray( boundingSphere.center );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.boundingSphere = new Sphere( center, boundingSphere.radius );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.name ) { geometry.name = json.name; }\r\n\t\t\tif ( json.userData ) { geometry.userData = json.userData; }\r\n\r\n\t\t\treturn geometry;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tvar TYPED_ARRAYS = {\r\n\t\tInt8Array: Int8Array,\r\n\t\tUint8Array: Uint8Array,\r\n\t\t// Workaround for IE11 pre KB2929437. See #11440\r\n\t\tUint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,\r\n\t\tInt16Array: Int16Array,\r\n\t\tUint16Array: Uint16Array,\r\n\t\tInt32Array: Int32Array,\r\n\t\tUint32Array: Uint32Array,\r\n\t\tFloat32Array: Float32Array,\r\n\t\tFloat64Array: Float64Array\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ObjectLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ObjectLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;\r\n\t\t\tthis.resourcePath = this.resourcePath || path;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tvar json = null;\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tjson = JSON.parse( text );\r\n\r\n\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\tif ( onError !== undefined ) { onError( error ); }\r\n\r\n\t\t\t\t\tconsole.error( 'THREE:ObjectLoader: Can\\'t parse ' + url + '.', error.message );\r\n\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar metadata = json.metadata;\r\n\r\n\t\t\t\tif ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.ObjectLoader: Can\\'t load ' + url );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.parse( json, onLoad );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json, onLoad ) {\r\n\r\n\t\t\tvar shapes = this.parseShape( json.shapes );\r\n\t\t\tvar geometries = this.parseGeometries( json.geometries, shapes );\r\n\r\n\t\t\tvar images = this.parseImages( json.images, function () {\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) { onLoad( object ); }\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tvar textures = this.parseTextures( json.textures, images );\r\n\t\t\tvar materials = this.parseMaterials( json.materials, textures );\r\n\r\n\t\t\tvar object = this.parseObject( json.object, geometries, materials );\r\n\r\n\t\t\tif ( json.animations ) {\r\n\r\n\t\t\t\tobject.animations = this.parseAnimations( json.animations );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.images === undefined || json.images.length === 0 ) {\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) { onLoad( object ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t},\r\n\r\n\t\tparseShape: function ( json ) {\r\n\r\n\t\t\tvar shapes = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar shape = new Shape().fromJSON( json[ i ] );\r\n\r\n\t\t\t\t\tshapes[ shape.uuid ] = shape;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t},\r\n\r\n\t\tparseGeometries: function ( json, shapes ) {\r\n\r\n\t\t\tvar geometries = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tvar bufferGeometryLoader = new BufferGeometryLoader();\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar geometry;\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tswitch ( data.type ) {\r\n\r\n\t\t\t\t\t\tcase 'PlaneGeometry':\r\n\t\t\t\t\t\tcase 'PlaneBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.width,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'BoxGeometry':\r\n\t\t\t\t\t\tcase 'BoxBufferGeometry':\r\n\t\t\t\t\t\tcase 'CubeGeometry': // backwards compatible\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.width,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.depth,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.depthSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'CircleGeometry':\r\n\t\t\t\t\t\tcase 'CircleBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.segments,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'CylinderGeometry':\r\n\t\t\t\t\t\tcase 'CylinderBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radiusTop,\r\n\t\t\t\t\t\t\t\tdata.radiusBottom,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.openEnded,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'ConeGeometry':\r\n\t\t\t\t\t\tcase 'ConeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.openEnded,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'SphereGeometry':\r\n\t\t\t\t\t\tcase 'SphereBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.phiStart,\r\n\t\t\t\t\t\t\t\tdata.phiLength,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'DodecahedronGeometry':\r\n\t\t\t\t\t\tcase 'DodecahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'IcosahedronGeometry':\r\n\t\t\t\t\t\tcase 'IcosahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'OctahedronGeometry':\r\n\t\t\t\t\t\tcase 'OctahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'TetrahedronGeometry':\r\n\t\t\t\t\t\tcase 'TetrahedronBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.detail\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'RingGeometry':\r\n\t\t\t\t\t\tcase 'RingBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.innerRadius,\r\n\t\t\t\t\t\t\t\tdata.outerRadius,\r\n\t\t\t\t\t\t\t\tdata.thetaSegments,\r\n\t\t\t\t\t\t\t\tdata.phiSegments,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TorusGeometry':\r\n\t\t\t\t\t\tcase 'TorusBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.tube,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.arc\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TorusKnotGeometry':\r\n\t\t\t\t\t\tcase 'TorusKnotBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.tube,\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.p,\r\n\t\t\t\t\t\t\t\tdata.q\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TubeGeometry':\r\n\t\t\t\t\t\tcase 'TubeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\t// This only works for built-in curves (e.g. CatmullRomCurve3).\r\n\t\t\t\t\t\t\t// User defined curves or instances of CurvePath will not be deserialized.\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tnew Curves[ data.path.type ]().fromJSON( data.path ),\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.closed\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'LatheGeometry':\r\n\t\t\t\t\t\tcase 'LatheBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.points,\r\n\t\t\t\t\t\t\t\tdata.segments,\r\n\t\t\t\t\t\t\t\tdata.phiStart,\r\n\t\t\t\t\t\t\t\tdata.phiLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'PolyhedronGeometry':\r\n\t\t\t\t\t\tcase 'PolyhedronBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.vertices,\r\n\t\t\t\t\t\t\t\tdata.indices,\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.details\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'ShapeGeometry':\r\n\t\t\t\t\t\tcase 'ShapeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tvar geometryShapes = [];\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar shape = shapes[ data.shapes[ j ] ];\r\n\r\n\t\t\t\t\t\t\t\tgeometryShapes.push( shape );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tgeometryShapes,\r\n\t\t\t\t\t\t\t\tdata.curveSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\r\n\t\t\t\t\t\tcase 'ExtrudeGeometry':\r\n\t\t\t\t\t\tcase 'ExtrudeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tvar geometryShapes = [];\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar shape = shapes[ data.shapes[ j ] ];\r\n\r\n\t\t\t\t\t\t\t\tgeometryShapes.push( shape );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tvar extrudePath = data.options.extrudePath;\r\n\r\n\t\t\t\t\t\t\tif ( extrudePath !== undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tdata.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tgeometryShapes,\r\n\t\t\t\t\t\t\t\tdata.options\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'BufferGeometry':\r\n\t\t\t\t\t\tcase 'InstancedBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = bufferGeometryLoader.parse( data );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'Geometry':\r\n\r\n\t\t\t\t\t\t\tif ( 'THREE' in window && 'LegacyJSONLoader' in THREE ) {\r\n\r\n\t\t\t\t\t\t\t\tvar geometryLoader = new THREE.LegacyJSONLoader();\r\n\t\t\t\t\t\t\t\tgeometry = geometryLoader.parse( data, this.resourcePath ).geometry;\r\n\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.ObjectLoader: You have to import LegacyJSONLoader in order load geometry data of type \"Geometry\".' );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Unsupported geometry type \"' + data.type + '\"' );\r\n\r\n\t\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.uuid = data.uuid;\r\n\r\n\t\t\t\t\tif ( data.name !== undefined ) { geometry.name = data.name; }\r\n\t\t\t\t\tif ( geometry.isBufferGeometry === true && data.userData !== undefined ) { geometry.userData = data.userData; }\r\n\r\n\t\t\t\t\tgeometries[ data.uuid ] = geometry;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometries;\r\n\r\n\t\t},\r\n\r\n\t\tparseMaterials: function ( json, textures ) {\r\n\r\n\t\t\tvar cache = {}; // MultiMaterial\r\n\t\t\tvar materials = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tvar loader = new MaterialLoader();\r\n\t\t\t\tloader.setTextures( textures );\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tif ( data.type === 'MultiMaterial' ) {\r\n\r\n\t\t\t\t\t\t// Deprecated\r\n\r\n\t\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j < data.materials.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar material = data.materials[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( cache[ material.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tcache[ material.uuid ] = loader.parse( material );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tarray.push( cache[ material.uuid ] );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tmaterials[ data.uuid ] = array;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( cache[ data.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tcache[ data.uuid ] = loader.parse( data );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tmaterials[ data.uuid ] = cache[ data.uuid ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn materials;\r\n\r\n\t\t},\r\n\r\n\t\tparseAnimations: function ( json ) {\r\n\r\n\t\t\tvar animations = [];\r\n\r\n\t\t\tfor ( var i = 0; i < json.length; i ++ ) {\r\n\r\n\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\tvar clip = AnimationClip.parse( data );\r\n\r\n\t\t\t\tif ( data.uuid !== undefined ) { clip.uuid = data.uuid; }\r\n\r\n\t\t\t\tanimations.push( clip );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn animations;\r\n\r\n\t\t},\r\n\r\n\t\tparseImages: function ( json, onLoad ) {\r\n\r\n\t\t\tvar scope = this;\r\n\t\t\tvar images = {};\r\n\r\n\t\t\tfunction loadImage( url ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\treturn loader.load( url, function () {\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, undefined, function () {\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json !== undefined && json.length > 0 ) {\r\n\r\n\t\t\t\tvar manager = new LoadingManager( onLoad );\r\n\r\n\t\t\t\tvar loader = new ImageLoader( manager );\r\n\t\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\t\t\tfor ( var i = 0, il = json.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar image = json[ i ];\r\n\t\t\t\t\tvar url = image.url;\r\n\r\n\t\t\t\t\tif ( Array.isArray( url ) ) {\r\n\r\n\t\t\t\t\t\t// load array of images e.g CubeTexture\r\n\r\n\t\t\t\t\t\timages[ image.uuid ] = [];\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = url.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar currentUrl = url[ j ];\r\n\r\n\t\t\t\t\t\t\tvar path = /^(\\/\\/)|([a-z]+:(\\/\\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;\r\n\r\n\t\t\t\t\t\t\timages[ image.uuid ].push( loadImage( path ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// load single image\r\n\r\n\t\t\t\t\t\tvar path = /^(\\/\\/)|([a-z]+:(\\/\\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;\r\n\r\n\t\t\t\t\t\timages[ image.uuid ] = loadImage( path );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn images;\r\n\r\n\t\t},\r\n\r\n\t\tparseTextures: function ( json, images ) {\r\n\r\n\t\t\tfunction parseConstant( value, type ) {\r\n\r\n\t\t\t\tif ( typeof value === 'number' ) { return value; }\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );\r\n\r\n\t\t\t\treturn type[ value ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar textures = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tif ( data.image === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: No \"image\" specified for', data.uuid );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( images[ data.image ] === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined image', data.image );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar texture;\r\n\r\n\t\t\t\t\tif ( Array.isArray( images[ data.image ] ) ) {\r\n\r\n\t\t\t\t\t\ttexture = new CubeTexture( images[ data.image ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ttexture = new Texture( images[ data.image ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\ttexture.uuid = data.uuid;\r\n\r\n\t\t\t\t\tif ( data.name !== undefined ) { texture.name = data.name; }\r\n\r\n\t\t\t\t\tif ( data.mapping !== undefined ) { texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); }\r\n\r\n\t\t\t\t\tif ( data.offset !== undefined ) { texture.offset.fromArray( data.offset ); }\r\n\t\t\t\t\tif ( data.repeat !== undefined ) { texture.repeat.fromArray( data.repeat ); }\r\n\t\t\t\t\tif ( data.center !== undefined ) { texture.center.fromArray( data.center ); }\r\n\t\t\t\t\tif ( data.rotation !== undefined ) { texture.rotation = data.rotation; }\r\n\r\n\t\t\t\t\tif ( data.wrap !== undefined ) {\r\n\r\n\t\t\t\t\t\ttexture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );\r\n\t\t\t\t\t\ttexture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( data.format !== undefined ) { texture.format = data.format; }\r\n\t\t\t\t\tif ( data.type !== undefined ) { texture.type = data.type; }\r\n\t\t\t\t\tif ( data.encoding !== undefined ) { texture.encoding = data.encoding; }\r\n\r\n\t\t\t\t\tif ( data.minFilter !== undefined ) { texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); }\r\n\t\t\t\t\tif ( data.magFilter !== undefined ) { texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); }\r\n\t\t\t\t\tif ( data.anisotropy !== undefined ) { texture.anisotropy = data.anisotropy; }\r\n\r\n\t\t\t\t\tif ( data.flipY !== undefined ) { texture.flipY = data.flipY; }\r\n\r\n\t\t\t\t\tif ( data.premultiplyAlpha !== undefined ) { texture.premultiplyAlpha = data.premultiplyAlpha; }\r\n\t\t\t\t\tif ( data.unpackAlignment !== undefined ) { texture.unpackAlignment = data.unpackAlignment; }\r\n\r\n\t\t\t\t\ttextures[ data.uuid ] = texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn textures;\r\n\r\n\t\t},\r\n\r\n\t\tparseObject: function ( data, geometries, materials ) {\r\n\r\n\t\t\tvar object;\r\n\r\n\t\t\tfunction getGeometry( name ) {\r\n\r\n\t\t\t\tif ( geometries[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined geometry', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn geometries[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getMaterial( name ) {\r\n\r\n\t\t\t\tif ( name === undefined ) { return undefined; }\r\n\r\n\t\t\t\tif ( Array.isArray( name ) ) {\r\n\r\n\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = name.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar uuid = name[ i ];\r\n\r\n\t\t\t\t\t\tif ( materials[ uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined material', uuid );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tarray.push( materials[ uuid ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn array;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( materials[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined material', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn materials[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( data.type ) {\r\n\r\n\t\t\t\tcase 'Scene':\r\n\r\n\t\t\t\t\tobject = new Scene();\r\n\r\n\t\t\t\t\tif ( data.background !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( Number.isInteger( data.background ) ) {\r\n\r\n\t\t\t\t\t\t\tobject.background = new Color( data.background );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( data.fog !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( data.fog.type === 'Fog' ) {\r\n\r\n\t\t\t\t\t\t\tobject.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );\r\n\r\n\t\t\t\t\t\t} else if ( data.fog.type === 'FogExp2' ) {\r\n\r\n\t\t\t\t\t\t\tobject.fog = new FogExp2( data.fog.color, data.fog.density );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PerspectiveCamera':\r\n\r\n\t\t\t\t\tobject = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );\r\n\r\n\t\t\t\t\tif ( data.focus !== undefined ) { object.focus = data.focus; }\r\n\t\t\t\t\tif ( data.zoom !== undefined ) { object.zoom = data.zoom; }\r\n\t\t\t\t\tif ( data.filmGauge !== undefined ) { object.filmGauge = data.filmGauge; }\r\n\t\t\t\t\tif ( data.filmOffset !== undefined ) { object.filmOffset = data.filmOffset; }\r\n\t\t\t\t\tif ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); }\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'OrthographicCamera':\r\n\r\n\t\t\t\t\tobject = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );\r\n\r\n\t\t\t\t\tif ( data.zoom !== undefined ) { object.zoom = data.zoom; }\r\n\t\t\t\t\tif ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); }\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'AmbientLight':\r\n\r\n\t\t\t\t\tobject = new AmbientLight( data.color, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'DirectionalLight':\r\n\r\n\t\t\t\t\tobject = new DirectionalLight( data.color, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PointLight':\r\n\r\n\t\t\t\t\tobject = new PointLight( data.color, data.intensity, data.distance, data.decay );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'RectAreaLight':\r\n\r\n\t\t\t\t\tobject = new RectAreaLight( data.color, data.intensity, data.width, data.height );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'SpotLight':\r\n\r\n\t\t\t\t\tobject = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'HemisphereLight':\r\n\r\n\t\t\t\t\tobject = new HemisphereLight( data.color, data.groundColor, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'SkinnedMesh':\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );\r\n\r\n\t\t\t\tcase 'Mesh':\r\n\r\n\t\t\t\t\tvar geometry = getGeometry( data.geometry );\r\n\t\t\t\t\tvar material = getMaterial( data.material );\r\n\r\n\t\t\t\t\tif ( geometry.bones && geometry.bones.length > 0 ) {\r\n\r\n\t\t\t\t\t\tobject = new SkinnedMesh( geometry, material );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tobject = new Mesh( geometry, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'InstancedMesh':\r\n\r\n\t\t\t\t\tvar geometry = getGeometry( data.geometry );\r\n\t\t\t\t\tvar material = getMaterial( data.material );\r\n\t\t\t\t\tvar count = data.count;\r\n\t\t\t\t\tvar instanceMatrix = data.instanceMatrix;\r\n\r\n\t\t\t\t\tobject = new InstancedMesh( geometry, material, count );\r\n\t\t\t\t\tobject.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LOD':\r\n\r\n\t\t\t\t\tobject = new LOD();\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Line':\r\n\r\n\t\t\t\t\tobject = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LineLoop':\r\n\r\n\t\t\t\t\tobject = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LineSegments':\r\n\r\n\t\t\t\t\tobject = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PointCloud':\r\n\t\t\t\tcase 'Points':\r\n\r\n\t\t\t\t\tobject = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Sprite':\r\n\r\n\t\t\t\t\tobject = new Sprite( getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Group':\r\n\r\n\t\t\t\t\tobject = new Group();\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\r\n\t\t\t\t\tobject = new Object3D();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.uuid = data.uuid;\r\n\r\n\t\t\tif ( data.name !== undefined ) { object.name = data.name; }\r\n\r\n\t\t\tif ( data.matrix !== undefined ) {\r\n\r\n\t\t\t\tobject.matrix.fromArray( data.matrix );\r\n\r\n\t\t\t\tif ( data.matrixAutoUpdate !== undefined ) { object.matrixAutoUpdate = data.matrixAutoUpdate; }\r\n\t\t\t\tif ( object.matrixAutoUpdate ) { object.matrix.decompose( object.position, object.quaternion, object.scale ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( data.position !== undefined ) { object.position.fromArray( data.position ); }\r\n\t\t\t\tif ( data.rotation !== undefined ) { object.rotation.fromArray( data.rotation ); }\r\n\t\t\t\tif ( data.quaternion !== undefined ) { object.quaternion.fromArray( data.quaternion ); }\r\n\t\t\t\tif ( data.scale !== undefined ) { object.scale.fromArray( data.scale ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.castShadow !== undefined ) { object.castShadow = data.castShadow; }\r\n\t\t\tif ( data.receiveShadow !== undefined ) { object.receiveShadow = data.receiveShadow; }\r\n\r\n\t\t\tif ( data.shadow ) {\r\n\r\n\t\t\t\tif ( data.shadow.bias !== undefined ) { object.shadow.bias = data.shadow.bias; }\r\n\t\t\t\tif ( data.shadow.radius !== undefined ) { object.shadow.radius = data.shadow.radius; }\r\n\t\t\t\tif ( data.shadow.mapSize !== undefined ) { object.shadow.mapSize.fromArray( data.shadow.mapSize ); }\r\n\t\t\t\tif ( data.shadow.camera !== undefined ) { object.shadow.camera = this.parseObject( data.shadow.camera ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.visible !== undefined ) { object.visible = data.visible; }\r\n\t\t\tif ( data.frustumCulled !== undefined ) { object.frustumCulled = data.frustumCulled; }\r\n\t\t\tif ( data.renderOrder !== undefined ) { object.renderOrder = data.renderOrder; }\r\n\t\t\tif ( data.userData !== undefined ) { object.userData = data.userData; }\r\n\t\t\tif ( data.layers !== undefined ) { object.layers.mask = data.layers; }\r\n\r\n\t\t\tif ( data.children !== undefined ) {\r\n\r\n\t\t\t\tvar children = data.children;\r\n\r\n\t\t\t\tfor ( var i = 0; i < children.length; i ++ ) {\r\n\r\n\t\t\t\t\tobject.add( this.parseObject( children[ i ], geometries, materials ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.type === 'LOD' ) {\r\n\r\n\t\t\t\tif ( data.autoUpdate !== undefined ) { object.autoUpdate = data.autoUpdate; }\r\n\r\n\t\t\t\tvar levels = data.levels;\r\n\r\n\t\t\t\tfor ( var l = 0; l < levels.length; l ++ ) {\r\n\r\n\t\t\t\t\tvar level = levels[ l ];\r\n\t\t\t\t\tvar child = object.getObjectByProperty( 'uuid', level.object );\r\n\r\n\t\t\t\t\tif ( child !== undefined ) {\r\n\r\n\t\t\t\t\t\tobject.addLevel( child, level.distance );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tvar TEXTURE_MAPPING = {\r\n\t\tUVMapping: UVMapping,\r\n\t\tCubeReflectionMapping: CubeReflectionMapping,\r\n\t\tCubeRefractionMapping: CubeRefractionMapping,\r\n\t\tEquirectangularReflectionMapping: EquirectangularReflectionMapping,\r\n\t\tEquirectangularRefractionMapping: EquirectangularRefractionMapping,\r\n\t\tSphericalReflectionMapping: SphericalReflectionMapping,\r\n\t\tCubeUVReflectionMapping: CubeUVReflectionMapping,\r\n\t\tCubeUVRefractionMapping: CubeUVRefractionMapping\r\n\t};\r\n\r\n\tvar TEXTURE_WRAPPING = {\r\n\t\tRepeatWrapping: RepeatWrapping,\r\n\t\tClampToEdgeWrapping: ClampToEdgeWrapping,\r\n\t\tMirroredRepeatWrapping: MirroredRepeatWrapping\r\n\t};\r\n\r\n\tvar TEXTURE_FILTER = {\r\n\t\tNearestFilter: NearestFilter,\r\n\t\tNearestMipmapNearestFilter: NearestMipmapNearestFilter,\r\n\t\tNearestMipmapLinearFilter: NearestMipmapLinearFilter,\r\n\t\tLinearFilter: LinearFilter,\r\n\t\tLinearMipmapNearestFilter: LinearMipmapNearestFilter,\r\n\t\tLinearMipmapLinearFilter: LinearMipmapLinearFilter\r\n\t};\n\n\t/**\r\n\t * @author thespite / http://clicktorelease.com/\r\n\t */\r\n\r\n\r\n\tfunction ImageBitmapLoader( manager ) {\r\n\r\n\t\tif ( typeof createImageBitmap === 'undefined' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( typeof fetch === 'undefined' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );\r\n\r\n\t\t}\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t\tthis.options = undefined;\r\n\r\n\t}\r\n\r\n\tImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ImageBitmapLoader,\r\n\r\n\t\tsetOptions: function setOptions( options ) {\r\n\r\n\t\t\tthis.options = options;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( url === undefined ) { url = ''; }\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfetch( url ).then( function ( res ) {\r\n\r\n\t\t\t\treturn res.blob();\r\n\r\n\t\t\t} ).then( function ( blob ) {\r\n\r\n\t\t\t\tif ( scope.options === undefined ) {\r\n\r\n\t\t\t\t\t// Workaround for FireFox. It causes an error if you pass options.\r\n\t\t\t\t\treturn createImageBitmap( blob );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn createImageBitmap( blob, scope.options );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} ).then( function ( imageBitmap ) {\r\n\r\n\t\t\t\tCache.add( url, imageBitmap );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( imageBitmap ); }\r\n\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t} ).catch( function ( e ) {\r\n\r\n\t\t\t\tif ( onError ) { onError( e ); }\r\n\r\n\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * minimal class for proxing functions to Path. Replaces old \"extractSubpaths()\"\r\n\t **/\r\n\r\n\tfunction ShapePath() {\r\n\r\n\t\tthis.type = 'ShapePath';\r\n\r\n\t\tthis.color = new Color();\r\n\r\n\t\tthis.subPaths = [];\r\n\t\tthis.currentPath = null;\r\n\r\n\t}\r\n\r\n\tObject.assign( ShapePath.prototype, {\r\n\r\n\t\tmoveTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPath = new Path();\r\n\t\t\tthis.subPaths.push( this.currentPath );\r\n\t\t\tthis.currentPath.moveTo( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlineTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPath.lineTo( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tquadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {\r\n\r\n\t\t\tthis.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tbezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {\r\n\r\n\t\t\tthis.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsplineThru: function ( pts ) {\r\n\r\n\t\t\tthis.currentPath.splineThru( pts );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoShapes: function ( isCCW, noHoles ) {\r\n\r\n\t\t\tfunction toShapesNoHoles( inSubpaths ) {\r\n\r\n\t\t\t\tvar shapes = [];\r\n\r\n\t\t\t\tfor ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar tmpPath = inSubpaths[ i ];\r\n\r\n\t\t\t\t\tvar tmpShape = new Shape();\r\n\t\t\t\t\ttmpShape.curves = tmpPath.curves;\r\n\r\n\t\t\t\t\tshapes.push( tmpShape );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn shapes;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction isPointInsidePolygon( inPt, inPolygon ) {\r\n\r\n\t\t\t\tvar polyLen = inPolygon.length;\r\n\r\n\t\t\t\t// inPt on polygon contour => immediate success or\r\n\t\t\t\t// toggling of inside/outside at every single! intersection point of an edge\r\n\t\t\t\t// with the horizontal line through inPt, left of inPt\r\n\t\t\t\t// not counting lowerY endpoints of edges and whole edges on that line\r\n\t\t\t\tvar inside = false;\r\n\t\t\t\tfor ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {\r\n\r\n\t\t\t\t\tvar edgeLowPt = inPolygon[ p ];\r\n\t\t\t\t\tvar edgeHighPt = inPolygon[ q ];\r\n\r\n\t\t\t\t\tvar edgeDx = edgeHighPt.x - edgeLowPt.x;\r\n\t\t\t\t\tvar edgeDy = edgeHighPt.y - edgeLowPt.y;\r\n\r\n\t\t\t\t\tif ( Math.abs( edgeDy ) > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t// not parallel\r\n\t\t\t\t\t\tif ( edgeDy < 0 ) {\r\n\r\n\t\t\t\t\t\t\tedgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;\r\n\t\t\t\t\t\t\tedgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) \t\t{ continue; }\r\n\r\n\t\t\t\t\t\tif ( inPt.y === edgeLowPt.y ) {\r\n\r\n\t\t\t\t\t\t\tif ( inPt.x === edgeLowPt.x )\t\t{ return\ttrue; }\t\t// inPt is on contour ?\r\n\t\t\t\t\t\t\t// continue;\t\t\t\t// no intersection or edgeLowPt => doesn't count !!!\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tvar perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );\r\n\t\t\t\t\t\t\tif ( perpEdge === 0 )\t\t\t\t{ return\ttrue; }\t\t// inPt is on contour ?\r\n\t\t\t\t\t\t\tif ( perpEdge < 0 ) \t\t\t\t{ continue; }\r\n\t\t\t\t\t\t\tinside = ! inside;\t\t// true intersection left of inPt\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// parallel or collinear\r\n\t\t\t\t\t\tif ( inPt.y !== edgeLowPt.y ) \t\t{ continue; }\t\t\t// parallel\r\n\t\t\t\t\t\t// edge lies on the same horizontal line as inPt\r\n\t\t\t\t\t\tif ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||\r\n\t\t\t\t\t\t\t ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )\t\t{ return\ttrue; }\t// inPt: Point on contour !\r\n\t\t\t\t\t\t// continue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn\tinside;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar isClockWise = ShapeUtils.isClockWise;\r\n\r\n\t\t\tvar subPaths = this.subPaths;\r\n\t\t\tif ( subPaths.length === 0 ) { return []; }\r\n\r\n\t\t\tif ( noHoles === true )\t{ return\ttoShapesNoHoles( subPaths ); }\r\n\r\n\r\n\t\t\tvar solid, tmpPath, tmpShape, shapes = [];\r\n\r\n\t\t\tif ( subPaths.length === 1 ) {\r\n\r\n\t\t\t\ttmpPath = subPaths[ 0 ];\r\n\t\t\t\ttmpShape = new Shape();\r\n\t\t\t\ttmpShape.curves = tmpPath.curves;\r\n\t\t\t\tshapes.push( tmpShape );\r\n\t\t\t\treturn shapes;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );\r\n\t\t\tholesFirst = isCCW ? ! holesFirst : holesFirst;\r\n\r\n\t\t\t// console.log(\"Holes first\", holesFirst);\r\n\r\n\t\t\tvar betterShapeHoles = [];\r\n\t\t\tvar newShapes = [];\r\n\t\t\tvar newShapeHoles = [];\r\n\t\t\tvar mainIdx = 0;\r\n\t\t\tvar tmpPoints;\r\n\r\n\t\t\tnewShapes[ mainIdx ] = undefined;\r\n\t\t\tnewShapeHoles[ mainIdx ] = [];\r\n\r\n\t\t\tfor ( var i = 0, l = subPaths.length; i < l; i ++ ) {\r\n\r\n\t\t\t\ttmpPath = subPaths[ i ];\r\n\t\t\t\ttmpPoints = tmpPath.getPoints();\r\n\t\t\t\tsolid = isClockWise( tmpPoints );\r\n\t\t\t\tsolid = isCCW ? ! solid : solid;\r\n\r\n\t\t\t\tif ( solid ) {\r\n\r\n\t\t\t\t\tif ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )\t{ mainIdx ++; }\r\n\r\n\t\t\t\t\tnewShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };\r\n\t\t\t\t\tnewShapes[ mainIdx ].s.curves = tmpPath.curves;\r\n\r\n\t\t\t\t\tif ( holesFirst )\t{ mainIdx ++; }\r\n\t\t\t\t\tnewShapeHoles[ mainIdx ] = [];\r\n\r\n\t\t\t\t\t//console.log('cw', i);\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tnewShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );\r\n\r\n\t\t\t\t\t//console.log('ccw', i);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// only Holes? -> probably all Shapes with wrong orientation\r\n\t\t\tif ( ! newShapes[ 0 ] )\t{ return\ttoShapesNoHoles( subPaths ); }\r\n\r\n\r\n\t\t\tif ( newShapes.length > 1 ) {\r\n\r\n\t\t\t\tvar ambiguous = false;\r\n\t\t\t\tvar toChange = [];\r\n\r\n\t\t\t\tfor ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {\r\n\r\n\t\t\t\t\tbetterShapeHoles[ sIdx ] = [];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {\r\n\r\n\t\t\t\t\tvar sho = newShapeHoles[ sIdx ];\r\n\r\n\t\t\t\t\tfor ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {\r\n\r\n\t\t\t\t\t\tvar ho = sho[ hIdx ];\r\n\t\t\t\t\t\tvar hole_unassigned = true;\r\n\r\n\t\t\t\t\t\tfor ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( sIdx !== s2Idx )\t{ toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); }\r\n\t\t\t\t\t\t\t\tif ( hole_unassigned ) {\r\n\r\n\t\t\t\t\t\t\t\t\thole_unassigned = false;\r\n\t\t\t\t\t\t\t\t\tbetterShapeHoles[ s2Idx ].push( ho );\r\n\r\n\t\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\t\tambiguous = true;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( hole_unassigned ) {\r\n\r\n\t\t\t\t\t\t\tbetterShapeHoles[ sIdx ].push( ho );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t\t// console.log(\"ambiguous: \", ambiguous);\r\n\t\t\t\tif ( toChange.length > 0 ) {\r\n\r\n\t\t\t\t\t// console.log(\"to change: \", toChange);\r\n\t\t\t\t\tif ( ! ambiguous )\t{ newShapeHoles = betterShapeHoles; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar tmpHoles;\r\n\r\n\t\t\tfor ( var i = 0, il = newShapes.length; i < il; i ++ ) {\r\n\r\n\t\t\t\ttmpShape = newShapes[ i ].s;\r\n\t\t\t\tshapes.push( tmpShape );\r\n\t\t\t\ttmpHoles = newShapeHoles[ i ];\r\n\r\n\t\t\t\tfor ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\ttmpShape.holes.push( tmpHoles[ j ].h );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//console.log(\"shape\", shapes);\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction Font( data ) {\r\n\r\n\t\tthis.type = 'Font';\r\n\r\n\t\tthis.data = data;\r\n\r\n\t}\r\n\r\n\tObject.assign( Font.prototype, {\r\n\r\n\t\tisFont: true,\r\n\r\n\t\tgenerateShapes: function ( text, size ) {\r\n\r\n\t\t\tif ( size === undefined ) { size = 100; }\r\n\r\n\t\t\tvar shapes = [];\r\n\t\t\tvar paths = createPaths( text, size, this.data );\r\n\r\n\t\t\tfor ( var p = 0, pl = paths.length; p < pl; p ++ ) {\r\n\r\n\t\t\t\tArray.prototype.push.apply( shapes, paths[ p ].toShapes() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction createPaths( text, size, data ) {\r\n\r\n\t\tvar chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // see #13988\r\n\t\tvar scale = size / data.resolution;\r\n\t\tvar line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;\r\n\r\n\t\tvar paths = [];\r\n\r\n\t\tvar offsetX = 0, offsetY = 0;\r\n\r\n\t\tfor ( var i = 0; i < chars.length; i ++ ) {\r\n\r\n\t\t\tvar char = chars[ i ];\r\n\r\n\t\t\tif ( char === '\\n' ) {\r\n\r\n\t\t\t\toffsetX = 0;\r\n\t\t\t\toffsetY -= line_height;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar ret = createPath( char, scale, offsetX, offsetY, data );\r\n\t\t\t\toffsetX += ret.offsetX;\r\n\t\t\t\tpaths.push( ret.path );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn paths;\r\n\r\n\t}\r\n\r\n\tfunction createPath( char, scale, offsetX, offsetY, data ) {\r\n\r\n\t\tvar glyph = data.glyphs[ char ] || data.glyphs[ '?' ];\r\n\r\n\t\tif ( ! glyph ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Font: character \"' + char + '\" does not exists in font family ' + data.familyName + '.' );\r\n\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tvar path = new ShapePath();\r\n\r\n\t\tvar x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;\r\n\r\n\t\tif ( glyph.o ) {\r\n\r\n\t\t\tvar outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );\r\n\r\n\t\t\tfor ( var i = 0, l = outline.length; i < l; ) {\r\n\r\n\t\t\t\tvar action = outline[ i ++ ];\r\n\r\n\t\t\t\tswitch ( action ) {\r\n\r\n\t\t\t\t\tcase 'm': // moveTo\r\n\r\n\t\t\t\t\t\tx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\ty = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.moveTo( x, y );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'l': // lineTo\r\n\r\n\t\t\t\t\t\tx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\ty = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.lineTo( x, y );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'q': // quadraticCurveTo\r\n\r\n\t\t\t\t\t\tcpx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx1 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy1 = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.quadraticCurveTo( cpx1, cpy1, cpx, cpy );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'b': // bezierCurveTo\r\n\r\n\t\t\t\t\t\tcpx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx1 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy1 = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx2 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy2 = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn { offsetX: glyph.ha * scale, path: path };\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction FontLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tFontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: FontLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tvar json;\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tjson = JSON.parse( text );\r\n\r\n\t\t\t\t} catch ( e ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );\r\n\t\t\t\t\tjson = JSON.parse( text.substring( 65, text.length - 2 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar font = scope.parse( json );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( font ); }\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\treturn new Font( json );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _context;\r\n\r\n\tvar AudioContext = {\r\n\r\n\t\tgetContext: function () {\r\n\r\n\t\t\tif ( _context === undefined ) {\r\n\r\n\t\t\t\t_context = new ( window.AudioContext || window.webkitAudioContext )();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn _context;\r\n\r\n\t\t},\r\n\r\n\t\tsetContext: function ( value ) {\r\n\r\n\t\t\t_context = value;\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author Reece Aaron Lecrivain / http://reecenotes.com/\r\n\t */\r\n\r\n\tfunction AudioLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tAudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: AudioLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\t// Create a copy of the buffer. The `decodeAudioData` method\r\n\t\t\t\t// detaches the buffer when complete, preventing reuse.\r\n\t\t\t\tvar bufferCopy = buffer.slice( 0 );\r\n\r\n\t\t\t\tvar context = AudioContext.getContext();\r\n\t\t\t\tcontext.decodeAudioData( bufferCopy, function ( audioBuffer ) {\r\n\r\n\t\t\t\t\tonLoad( audioBuffer );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * Primary reference:\r\n\t * https://graphics.stanford.edu/papers/envmap/envmap.pdf\r\n\t *\r\n\t * Secondary reference:\r\n\t * https://www.ppsloan.org/publications/StupidSH36.pdf\r\n\t */\r\n\r\n\t// 3-band SH defined by 9 coefficients\r\n\r\n\tfunction SphericalHarmonics3() {\r\n\r\n\t\tthis.coefficients = [];\r\n\r\n\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\tthis.coefficients.push( new Vector3() );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( SphericalHarmonics3.prototype, {\r\n\r\n\t\tisSphericalHarmonics3: true,\r\n\r\n\t\tset: function ( coefficients ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].copy( coefficients[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tzero: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].set( 0, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// get the radiance in the direction of the normal\r\n\t\t// target is a Vector3\r\n\t\tgetAt: function ( normal, target ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\tvar coeff = this.coefficients;\r\n\r\n\t\t\t// band 0\r\n\t\t\ttarget.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );\r\n\r\n\t\t\t// band 1\r\n\t\t\ttarget.addScale( coeff[ 1 ], 0.488603 * y );\r\n\t\t\ttarget.addScale( coeff[ 2 ], 0.488603 * z );\r\n\t\t\ttarget.addScale( coeff[ 3 ], 0.488603 * x );\r\n\r\n\t\t\t// band 2\r\n\t\t\ttarget.addScale( coeff[ 4 ], 1.092548 * ( x * y ) );\r\n\t\t\ttarget.addScale( coeff[ 5 ], 1.092548 * ( y * z ) );\r\n\t\t\ttarget.addScale( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );\r\n\t\t\ttarget.addScale( coeff[ 7 ], 1.092548 * ( x * z ) );\r\n\t\t\ttarget.addScale( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\t// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal\r\n\t\t// target is a Vector3\r\n\t\t// https://graphics.stanford.edu/papers/envmap/envmap.pdf\r\n\t\tgetIrradianceAt: function ( normal, target ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\tvar coeff = this.coefficients;\r\n\r\n\t\t\t// band 0\r\n\t\t\ttarget.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095\r\n\r\n\t\t\t// band 1\r\n\t\t\ttarget.addScale( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603\r\n\t\t\ttarget.addScale( coeff[ 2 ], 2.0 * 0.511664 * z );\r\n\t\t\ttarget.addScale( coeff[ 3 ], 2.0 * 0.511664 * x );\r\n\r\n\t\t\t// band 2\r\n\t\t\ttarget.addScale( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548\r\n\t\t\ttarget.addScale( coeff[ 5 ], 2.0 * 0.429043 * y * z );\r\n\t\t\ttarget.addScale( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3\r\n\t\t\ttarget.addScale( coeff[ 7 ], 2.0 * 0.429043 * x * z );\r\n\t\t\ttarget.addScale( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( sh ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].add( sh.coefficients[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\r\n\t\tscale: function ( s ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].multiplyScalar( s );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( sh, alpha ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( sh ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tif ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( sh ) {\r\n\r\n\t\t\treturn this.set( sh.coefficients );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar coefficients = this.coefficients;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tcoefficients[ i ].fromArray( array, offset + ( i * 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar coefficients = this.coefficients;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tcoefficients[ i ].toArray( array, offset + ( i * 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( SphericalHarmonics3, {\r\n\r\n\t\t// evaluate the basis functions\r\n\t\t// shBasis is an Array[ 9 ]\r\n\t\tgetBasisAt: function ( normal, shBasis ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\t// band 0\r\n\t\t\tshBasis[ 0 ] = 0.282095;\r\n\r\n\t\t\t// band 1\r\n\t\t\tshBasis[ 1 ] = 0.488603 * y;\r\n\t\t\tshBasis[ 2 ] = 0.488603 * z;\r\n\t\t\tshBasis[ 3 ] = 0.488603 * x;\r\n\r\n\t\t\t// band 2\r\n\t\t\tshBasis[ 4 ] = 1.092548 * x * y;\r\n\t\t\tshBasis[ 5 ] = 1.092548 * y * z;\r\n\t\t\tshBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );\r\n\t\t\tshBasis[ 7 ] = 1.092548 * x * z;\r\n\t\t\tshBasis[ 8 ] = 0.546274 * ( x * x - y * y );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * A LightProbe is a source of indirect-diffuse light\r\n\t */\r\n\r\n\tfunction LightProbe( sh, intensity ) {\r\n\r\n\t\tLight.call( this, undefined, intensity );\r\n\r\n\t\tthis.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();\r\n\r\n\t}\r\n\r\n\tLightProbe.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: LightProbe,\r\n\r\n\t\tisLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.sh.copy( source.sh );\r\n\t\t\tthis.intensity = source.intensity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Light.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction HemisphereLightProbe( skyColor, groundColor, intensity ) {\r\n\r\n\t\tLightProbe.call( this, undefined, intensity );\r\n\r\n\t\tvar color1 = new Color().set( skyColor );\r\n\t\tvar color2 = new Color().set( groundColor );\r\n\r\n\t\tvar sky = new Vector3( color1.r, color1.g, color1.b );\r\n\t\tvar ground = new Vector3( color2.r, color2.g, color2.b );\r\n\r\n\t\t// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );\r\n\t\tvar c0 = Math.sqrt( Math.PI );\r\n\t\tvar c1 = c0 * Math.sqrt( 0.75 );\r\n\r\n\t\tthis.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );\r\n\t\tthis.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );\r\n\r\n\t}\r\n\r\n\tHemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {\r\n\r\n\t\tconstructor: HemisphereLightProbe,\r\n\r\n\t\tisHemisphereLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) { // modifying colors not currently supported\r\n\r\n\t\t\tLightProbe.prototype.copy.call( this, source );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = LightProbe.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction AmbientLightProbe( color, intensity ) {\r\n\r\n\t\tLightProbe.call( this, undefined, intensity );\r\n\r\n\t\tvar color1 = new Color().set( color );\r\n\r\n\t\t// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );\r\n\t\tthis.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );\r\n\r\n\t}\r\n\r\n\tAmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {\r\n\r\n\t\tconstructor: AmbientLightProbe,\r\n\r\n\t\tisAmbientLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) { // modifying color not currently supported\r\n\r\n\t\t\tLightProbe.prototype.copy.call( this, source );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = LightProbe.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _eyeRight = new Matrix4();\r\n\tvar _eyeLeft = new Matrix4();\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction StereoCamera() {\r\n\r\n\t\tthis.type = 'StereoCamera';\r\n\r\n\t\tthis.aspect = 1;\r\n\r\n\t\tthis.eyeSep = 0.064;\r\n\r\n\t\tthis.cameraL = new PerspectiveCamera();\r\n\t\tthis.cameraL.layers.enable( 1 );\r\n\t\tthis.cameraL.matrixAutoUpdate = false;\r\n\r\n\t\tthis.cameraR = new PerspectiveCamera();\r\n\t\tthis.cameraR.layers.enable( 2 );\r\n\t\tthis.cameraR.matrixAutoUpdate = false;\r\n\r\n\t\tthis._cache = {\r\n\t\t\tfocus: null,\r\n\t\t\tfov: null,\r\n\t\t\taspect: null,\r\n\t\t\tnear: null,\r\n\t\t\tfar: null,\r\n\t\t\tzoom: null,\r\n\t\t\teyeSep: null\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( StereoCamera.prototype, {\r\n\r\n\t\tupdate: function ( camera ) {\r\n\r\n\t\t\tvar cache = this._cache;\r\n\r\n\t\t\tvar needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||\r\n\t\t\t\tcache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||\r\n\t\t\t\tcache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;\r\n\r\n\t\t\tif ( needsUpdate ) {\r\n\r\n\t\t\t\tcache.focus = camera.focus;\r\n\t\t\t\tcache.fov = camera.fov;\r\n\t\t\t\tcache.aspect = camera.aspect * this.aspect;\r\n\t\t\t\tcache.near = camera.near;\r\n\t\t\t\tcache.far = camera.far;\r\n\t\t\t\tcache.zoom = camera.zoom;\r\n\t\t\t\tcache.eyeSep = this.eyeSep;\r\n\r\n\t\t\t\t// Off-axis stereoscopic effect based on\r\n\t\t\t\t// http://paulbourke.net/stereographics/stereorender/\r\n\r\n\t\t\t\tvar projectionMatrix = camera.projectionMatrix.clone();\r\n\t\t\t\tvar eyeSepHalf = cache.eyeSep / 2;\r\n\t\t\t\tvar eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;\r\n\t\t\t\tvar ymax = ( cache.near * Math.tan( _Math.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;\r\n\t\t\t\tvar xmin, xmax;\r\n\r\n\t\t\t\t// translate xOffset\r\n\r\n\t\t\t\t_eyeLeft.elements[ 12 ] = - eyeSepHalf;\r\n\t\t\t\t_eyeRight.elements[ 12 ] = eyeSepHalf;\r\n\r\n\t\t\t\t// for left eye\r\n\r\n\t\t\t\txmin = - ymax * cache.aspect + eyeSepOnProjection;\r\n\t\t\t\txmax = ymax * cache.aspect + eyeSepOnProjection;\r\n\r\n\t\t\t\tprojectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );\r\n\t\t\t\tprojectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );\r\n\r\n\t\t\t\tthis.cameraL.projectionMatrix.copy( projectionMatrix );\r\n\r\n\t\t\t\t// for right eye\r\n\r\n\t\t\t\txmin = - ymax * cache.aspect - eyeSepOnProjection;\r\n\t\t\t\txmax = ymax * cache.aspect - eyeSepOnProjection;\r\n\r\n\t\t\t\tprojectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );\r\n\t\t\t\tprojectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );\r\n\r\n\t\t\t\tthis.cameraR.projectionMatrix.copy( projectionMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );\r\n\t\t\tthis.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Clock( autoStart ) {\r\n\r\n\t\tthis.autoStart = ( autoStart !== undefined ) ? autoStart : true;\r\n\r\n\t\tthis.startTime = 0;\r\n\t\tthis.oldTime = 0;\r\n\t\tthis.elapsedTime = 0;\r\n\r\n\t\tthis.running = false;\r\n\r\n\t}\r\n\r\n\tObject.assign( Clock.prototype, {\r\n\r\n\t\tstart: function () {\r\n\r\n\t\t\tthis.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732\r\n\r\n\t\t\tthis.oldTime = this.startTime;\r\n\t\t\tthis.elapsedTime = 0;\r\n\t\t\tthis.running = true;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tthis.getElapsedTime();\r\n\t\t\tthis.running = false;\r\n\t\t\tthis.autoStart = false;\r\n\r\n\t\t},\r\n\r\n\t\tgetElapsedTime: function () {\r\n\r\n\t\t\tthis.getDelta();\r\n\t\t\treturn this.elapsedTime;\r\n\r\n\t\t},\r\n\r\n\t\tgetDelta: function () {\r\n\r\n\t\t\tvar diff = 0;\r\n\r\n\t\t\tif ( this.autoStart && ! this.running ) {\r\n\r\n\t\t\t\tthis.start();\r\n\t\t\t\treturn 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.running ) {\r\n\r\n\t\t\t\tvar newTime = ( typeof performance === 'undefined' ? Date : performance ).now();\r\n\r\n\t\t\t\tdiff = ( newTime - this.oldTime ) / 1000;\r\n\t\t\t\tthis.oldTime = newTime;\r\n\r\n\t\t\t\tthis.elapsedTime += diff;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn diff;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _position$2 = new Vector3();\r\n\tvar _quaternion$3 = new Quaternion();\r\n\tvar _scale$1 = new Vector3();\r\n\tvar _orientation = new Vector3();\r\n\r\n\tfunction AudioListener() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'AudioListener';\r\n\r\n\t\tthis.context = AudioContext.getContext();\r\n\r\n\t\tthis.gain = this.context.createGain();\r\n\t\tthis.gain.connect( this.context.destination );\r\n\r\n\t\tthis.filter = null;\r\n\r\n\t\tthis.timeDelta = 0;\r\n\r\n\t\t// private\r\n\r\n\t\tthis._clock = new Clock();\r\n\r\n\t}\r\n\r\n\tAudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: AudioListener,\r\n\r\n\t\tgetInput: function () {\r\n\r\n\t\t\treturn this.gain;\r\n\r\n\t\t},\r\n\r\n\t\tremoveFilter: function ( ) {\r\n\r\n\t\t\tif ( this.filter !== null ) {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.filter );\r\n\t\t\t\tthis.filter.disconnect( this.context.destination );\r\n\t\t\t\tthis.gain.connect( this.context.destination );\r\n\t\t\t\tthis.filter = null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilter: function () {\r\n\r\n\t\t\treturn this.filter;\r\n\r\n\t\t},\r\n\r\n\t\tsetFilter: function ( value ) {\r\n\r\n\t\t\tif ( this.filter !== null ) {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.filter );\r\n\t\t\t\tthis.filter.disconnect( this.context.destination );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.context.destination );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.filter = value;\r\n\t\t\tthis.gain.connect( this.filter );\r\n\t\t\tthis.filter.connect( this.context.destination );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMasterVolume: function () {\r\n\r\n\t\t\treturn this.gain.gain.value;\r\n\r\n\t\t},\r\n\r\n\t\tsetMasterVolume: function ( value ) {\r\n\r\n\t\t\tthis.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tvar listener = this.context.listener;\r\n\t\t\tvar up = this.up;\r\n\r\n\t\t\tthis.timeDelta = this._clock.getDelta();\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );\r\n\r\n\t\t\t_orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );\r\n\r\n\t\t\tif ( listener.positionX ) {\r\n\r\n\t\t\t\t// code path for Chrome (see #14393)\r\n\r\n\t\t\t\tvar endTime = this.context.currentTime + this.timeDelta;\r\n\r\n\t\t\t\tlistener.positionX.linearRampToValueAtTime( _position$2.x, endTime );\r\n\t\t\t\tlistener.positionY.linearRampToValueAtTime( _position$2.y, endTime );\r\n\t\t\t\tlistener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );\r\n\t\t\t\tlistener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );\r\n\t\t\t\tlistener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );\r\n\t\t\t\tlistener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );\r\n\t\t\t\tlistener.upX.linearRampToValueAtTime( up.x, endTime );\r\n\t\t\t\tlistener.upY.linearRampToValueAtTime( up.y, endTime );\r\n\t\t\t\tlistener.upZ.linearRampToValueAtTime( up.z, endTime );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tlistener.setPosition( _position$2.x, _position$2.y, _position$2.z );\r\n\t\t\t\tlistener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Reece Aaron Lecrivain / http://reecenotes.com/\r\n\t */\r\n\r\n\tfunction Audio( listener ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Audio';\r\n\r\n\t\tthis.listener = listener;\r\n\t\tthis.context = listener.context;\r\n\r\n\t\tthis.gain = this.context.createGain();\r\n\t\tthis.gain.connect( listener.getInput() );\r\n\r\n\t\tthis.autoplay = false;\r\n\r\n\t\tthis.buffer = null;\r\n\t\tthis.detune = 0;\r\n\t\tthis.loop = false;\r\n\t\tthis.loopStart = 0;\r\n\t\tthis.loopEnd = 0;\r\n\t\tthis.offset = 0;\r\n\t\tthis.duration = undefined;\r\n\t\tthis.playbackRate = 1;\r\n\t\tthis.isPlaying = false;\r\n\t\tthis.hasPlaybackControl = true;\r\n\t\tthis.sourceType = 'empty';\r\n\r\n\t\tthis._startedAt = 0;\r\n\t\tthis._pausedAt = 0;\r\n\r\n\t\tthis.filters = [];\r\n\r\n\t}\r\n\r\n\tAudio.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Audio,\r\n\r\n\t\tgetOutput: function () {\r\n\r\n\t\t\treturn this.gain;\r\n\r\n\t\t},\r\n\r\n\t\tsetNodeSource: function ( audioNode ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'audioNode';\r\n\t\t\tthis.source = audioNode;\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMediaElementSource: function ( mediaElement ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'mediaNode';\r\n\t\t\tthis.source = this.context.createMediaElementSource( mediaElement );\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMediaStreamSource: function ( mediaStream ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'mediaStreamNode';\r\n\t\t\tthis.source = this.context.createMediaStreamSource( mediaStream );\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetBuffer: function ( audioBuffer ) {\r\n\r\n\t\t\tthis.buffer = audioBuffer;\r\n\t\t\tthis.sourceType = 'buffer';\r\n\r\n\t\t\tif ( this.autoplay ) { this.play(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tplay: function ( delay ) {\r\n\r\n\t\t\tif ( delay === undefined ) { delay = 0; }\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: Audio is already playing.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._startedAt = this.context.currentTime + delay;\r\n\r\n\t\t\tvar source = this.context.createBufferSource();\r\n\t\t\tsource.buffer = this.buffer;\r\n\t\t\tsource.loop = this.loop;\r\n\t\t\tsource.loopStart = this.loopStart;\r\n\t\t\tsource.loopEnd = this.loopEnd;\r\n\t\t\tsource.onended = this.onEnded.bind( this );\r\n\t\t\tsource.start( this._startedAt, this._pausedAt + this.offset, this.duration );\r\n\r\n\t\t\tthis.isPlaying = true;\r\n\r\n\t\t\tthis.source = source;\r\n\r\n\t\t\tthis.setDetune( this.detune );\r\n\t\t\tthis.setPlaybackRate( this.playbackRate );\r\n\r\n\t\t\treturn this.connect();\r\n\r\n\t\t},\r\n\r\n\t\tpause: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis._pausedAt = ( this.context.currentTime - this._startedAt ) * this.playbackRate;\r\n\r\n\t\t\t\tthis.source.stop();\r\n\t\t\t\tthis.source.onended = null;\r\n\r\n\t\t\t\tthis.isPlaying = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._pausedAt = 0;\r\n\r\n\t\t\tthis.source.stop();\r\n\t\t\tthis.source.onended = null;\r\n\t\t\tthis.isPlaying = false;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconnect: function () {\r\n\r\n\t\t\tif ( this.filters.length > 0 ) {\r\n\r\n\t\t\t\tthis.source.connect( this.filters[ 0 ] );\r\n\r\n\t\t\t\tfor ( var i = 1, l = this.filters.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tthis.filters[ i - 1 ].connect( this.filters[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.filters[ this.filters.length - 1 ].connect( this.getOutput() );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.source.connect( this.getOutput() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdisconnect: function () {\r\n\r\n\t\t\tif ( this.filters.length > 0 ) {\r\n\r\n\t\t\t\tthis.source.disconnect( this.filters[ 0 ] );\r\n\r\n\t\t\t\tfor ( var i = 1, l = this.filters.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tthis.filters[ i - 1 ].disconnect( this.filters[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.source.disconnect( this.getOutput() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilters: function () {\r\n\r\n\t\t\treturn this.filters;\r\n\r\n\t\t},\r\n\r\n\t\tsetFilters: function ( value ) {\r\n\r\n\t\t\tif ( ! value ) { value = []; }\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.disconnect();\r\n\t\t\t\tthis.filters = value;\r\n\t\t\t\tthis.connect();\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.filters = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetDetune: function ( value ) {\r\n\r\n\t\t\tthis.detune = value;\r\n\r\n\t\t\tif ( this.source.detune === undefined ) { return; } // only set detune when available\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetDetune: function () {\r\n\r\n\t\t\treturn this.detune;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilter: function () {\r\n\r\n\t\t\treturn this.getFilters()[ 0 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetFilter: function ( filter ) {\r\n\r\n\t\t\treturn this.setFilters( filter ? [ filter ] : [] );\r\n\r\n\t\t},\r\n\r\n\t\tsetPlaybackRate: function ( value ) {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.playbackRate = value;\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetPlaybackRate: function () {\r\n\r\n\t\t\treturn this.playbackRate;\r\n\r\n\t\t},\r\n\r\n\t\tonEnded: function () {\r\n\r\n\t\t\tthis.isPlaying = false;\r\n\r\n\t\t},\r\n\r\n\t\tgetLoop: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.loop;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoop: function ( value ) {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.loop = value;\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.loop = this.loop;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoopStart: function ( value ) {\r\n\r\n\t\t\tthis.loopStart = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoopEnd: function ( value ) {\r\n\r\n\t\t\tthis.loopEnd = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetVolume: function () {\r\n\r\n\t\t\treturn this.gain.gain.value;\r\n\r\n\t\t},\r\n\r\n\t\tsetVolume: function ( value ) {\r\n\r\n\t\t\tthis.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _position$3 = new Vector3();\r\n\tvar _quaternion$4 = new Quaternion();\r\n\tvar _scale$2 = new Vector3();\r\n\tvar _orientation$1 = new Vector3();\r\n\r\n\tfunction PositionalAudio( listener ) {\r\n\r\n\t\tAudio.call( this, listener );\r\n\r\n\t\tthis.panner = this.context.createPanner();\r\n\t\tthis.panner.panningModel = 'HRTF';\r\n\t\tthis.panner.connect( this.gain );\r\n\r\n\t}\r\n\r\n\tPositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {\r\n\r\n\t\tconstructor: PositionalAudio,\r\n\r\n\t\tgetOutput: function () {\r\n\r\n\t\t\treturn this.panner;\r\n\r\n\t\t},\r\n\r\n\t\tgetRefDistance: function () {\r\n\r\n\t\t\treturn this.panner.refDistance;\r\n\r\n\t\t},\r\n\r\n\t\tsetRefDistance: function ( value ) {\r\n\r\n\t\t\tthis.panner.refDistance = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetRolloffFactor: function () {\r\n\r\n\t\t\treturn this.panner.rolloffFactor;\r\n\r\n\t\t},\r\n\r\n\t\tsetRolloffFactor: function ( value ) {\r\n\r\n\t\t\tthis.panner.rolloffFactor = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetDistanceModel: function () {\r\n\r\n\t\t\treturn this.panner.distanceModel;\r\n\r\n\t\t},\r\n\r\n\t\tsetDistanceModel: function ( value ) {\r\n\r\n\t\t\tthis.panner.distanceModel = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMaxDistance: function () {\r\n\r\n\t\t\treturn this.panner.maxDistance;\r\n\r\n\t\t},\r\n\r\n\t\tsetMaxDistance: function ( value ) {\r\n\r\n\t\t\tthis.panner.maxDistance = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetDirectionalCone: function ( coneInnerAngle, coneOuterAngle, coneOuterGain ) {\r\n\r\n\t\t\tthis.panner.coneInnerAngle = coneInnerAngle;\r\n\t\t\tthis.panner.coneOuterAngle = coneOuterAngle;\r\n\t\t\tthis.panner.coneOuterGain = coneOuterGain;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tif ( this.hasPlaybackControl === true && this.isPlaying === false ) { return; }\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );\r\n\r\n\t\t\t_orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );\r\n\r\n\t\t\tvar panner = this.panner;\r\n\r\n\t\t\tif ( panner.positionX ) {\r\n\r\n\t\t\t\t// code path for Chrome and Firefox (see #14393)\r\n\r\n\t\t\t\tvar endTime = this.context.currentTime + this.listener.timeDelta;\r\n\r\n\t\t\t\tpanner.positionX.linearRampToValueAtTime( _position$3.x, endTime );\r\n\t\t\t\tpanner.positionY.linearRampToValueAtTime( _position$3.y, endTime );\r\n\t\t\t\tpanner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );\r\n\t\t\t\tpanner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );\r\n\t\t\t\tpanner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );\r\n\t\t\t\tpanner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tpanner.setPosition( _position$3.x, _position$3.y, _position$3.z );\r\n\t\t\t\tpanner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AudioAnalyser( audio, fftSize ) {\r\n\r\n\t\tthis.analyser = audio.context.createAnalyser();\r\n\t\tthis.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;\r\n\r\n\t\tthis.data = new Uint8Array( this.analyser.frequencyBinCount );\r\n\r\n\t\taudio.getOutput().connect( this.analyser );\r\n\r\n\t}\r\n\r\n\tObject.assign( AudioAnalyser.prototype, {\r\n\r\n\t\tgetFrequencyData: function () {\r\n\r\n\t\t\tthis.analyser.getByteFrequencyData( this.data );\r\n\r\n\t\t\treturn this.data;\r\n\r\n\t\t},\r\n\r\n\t\tgetAverageFrequency: function () {\r\n\r\n\t\t\tvar value = 0, data = this.getFrequencyData();\r\n\r\n\t\t\tfor ( var i = 0; i < data.length; i ++ ) {\r\n\r\n\t\t\t\tvalue += data[ i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn value / data.length;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Buffered scene graph property that allows weighted accumulation.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction PropertyMixer( binding, typeName, valueSize ) {\r\n\r\n\t\tthis.binding = binding;\r\n\t\tthis.valueSize = valueSize;\r\n\r\n\t\tvar bufferType = Float64Array,\r\n\t\t\tmixFunction;\r\n\r\n\t\tswitch ( typeName ) {\r\n\r\n\t\t\tcase 'quaternion':\r\n\t\t\t\tmixFunction = this._slerp;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'string':\r\n\t\t\tcase 'bool':\r\n\t\t\t\tbufferType = Array;\r\n\t\t\t\tmixFunction = this._select;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tmixFunction = this._lerp;\r\n\r\n\t\t}\r\n\r\n\t\tthis.buffer = new bufferType( valueSize * 4 );\r\n\t\t// layout: [ incoming | accu0 | accu1 | orig ]\r\n\t\t//\r\n\t\t// interpolators can use .buffer as their .result\r\n\t\t// the data then goes to 'incoming'\r\n\t\t//\r\n\t\t// 'accu0' and 'accu1' are used frame-interleaved for\r\n\t\t// the cumulative result and are compared to detect\r\n\t\t// changes\r\n\t\t//\r\n\t\t// 'orig' stores the original state of the property\r\n\r\n\t\tthis._mixBufferRegion = mixFunction;\r\n\r\n\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\tthis.useCount = 0;\r\n\t\tthis.referenceCount = 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( PropertyMixer.prototype, {\r\n\r\n\t\t// accumulate data in the 'incoming' region into 'accu'\r\n\t\taccumulate: function ( accuIndex, weight ) {\r\n\r\n\t\t\t// note: happily accumulating nothing when weight = 0, the caller knows\r\n\t\t\t// the weight and shouldn't have made the call in the first place\r\n\r\n\t\t\tvar buffer = this.buffer,\r\n\t\t\t\tstride = this.valueSize,\r\n\t\t\t\toffset = accuIndex * stride + stride,\r\n\r\n\t\t\t\tcurrentWeight = this.cumulativeWeight;\r\n\r\n\t\t\tif ( currentWeight === 0 ) {\r\n\r\n\t\t\t\t// accuN := incoming * weight\r\n\r\n\t\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ offset + i ] = buffer[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcurrentWeight = weight;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// accuN := accuN + incoming * weight\r\n\r\n\t\t\t\tcurrentWeight += weight;\r\n\t\t\t\tvar mix = weight / currentWeight;\r\n\t\t\t\tthis._mixBufferRegion( buffer, offset, 0, mix, stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cumulativeWeight = currentWeight;\r\n\r\n\t\t},\r\n\r\n\t\t// apply the state of 'accu' to the binding when accus differ\r\n\t\tapply: function ( accuIndex ) {\r\n\r\n\t\t\tvar stride = this.valueSize,\r\n\t\t\t\tbuffer = this.buffer,\r\n\t\t\t\toffset = accuIndex * stride + stride,\r\n\r\n\t\t\t\tweight = this.cumulativeWeight,\r\n\r\n\t\t\t\tbinding = this.binding;\r\n\r\n\t\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\t\tif ( weight < 1 ) {\r\n\r\n\t\t\t\t// accuN := accuN + original * ( 1 - cumulativeWeight )\r\n\r\n\t\t\t\tvar originalValueOffset = stride * 3;\r\n\r\n\t\t\t\tthis._mixBufferRegion(\r\n\t\t\t\t\tbuffer, offset, originalValueOffset, 1 - weight, stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = stride, e = stride + stride; i !== e; ++ i ) {\r\n\r\n\t\t\t\tif ( buffer[ i ] !== buffer[ i + stride ] ) {\r\n\r\n\t\t\t\t\t// value has changed -> update scene graph\r\n\r\n\t\t\t\t\tbinding.setValue( buffer, offset );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// remember the state of the bound property and copy it to both accus\r\n\t\tsaveOriginalState: function () {\r\n\r\n\t\t\tvar binding = this.binding;\r\n\r\n\t\t\tvar buffer = this.buffer,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toriginalValueOffset = stride * 3;\r\n\r\n\t\t\tbinding.getValue( buffer, originalValueOffset );\r\n\r\n\t\t\t// accu[0..1] := orig -- initially detect changes against the original\r\n\t\t\tfor ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {\r\n\r\n\t\t\t\tbuffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\t},\r\n\r\n\t\t// apply the state previously taken via 'saveOriginalState' to the binding\r\n\t\trestoreOriginalState: function () {\r\n\r\n\t\t\tvar originalValueOffset = this.valueSize * 3;\r\n\t\t\tthis.binding.setValue( this.buffer, originalValueOffset );\r\n\r\n\t\t},\r\n\r\n\r\n\t\t// mix functions\r\n\r\n\t\t_select: function ( buffer, dstOffset, srcOffset, t, stride ) {\r\n\r\n\t\t\tif ( t >= 0.5 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ dstOffset + i ] = buffer[ srcOffset + i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_slerp: function ( buffer, dstOffset, srcOffset, t ) {\r\n\r\n\t\t\tQuaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );\r\n\r\n\t\t},\r\n\r\n\t\t_lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {\r\n\r\n\t\t\tvar s = 1 - t;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tvar j = dstOffset + i;\r\n\r\n\t\t\t\tbuffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A reference to a real property in the scene graph.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\t// Characters [].:/ are reserved for track binding syntax.\r\n\tvar _RESERVED_CHARS_RE = '\\\\[\\\\]\\\\.:\\\\/';\r\n\tvar _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );\r\n\r\n\t// Attempts to allow node names from any language. ES5's `\\w` regexp matches\r\n\t// only latin characters, and the unicode \\p{L} is not yet supported. So\r\n\t// instead, we exclude reserved characters and match everything else.\r\n\tvar _wordChar = '[^' + _RESERVED_CHARS_RE + ']';\r\n\tvar _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\\\.', '' ) + ']';\r\n\r\n\t// Parent directories, delimited by '/' or ':'. Currently unused, but must\r\n\t// be matched to parse the rest of the track name.\r\n\tvar _directoryRe = /((?:WC+[\\/:])*)/.source.replace( 'WC', _wordChar );\r\n\r\n\t// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.\r\n\tvar _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );\r\n\r\n\t// Object on target node, and accessor. May not contain reserved\r\n\t// characters. Accessor may contain any character except closing bracket.\r\n\tvar _objectRe = /(?:\\.(WC+)(?:\\[(.+)\\])?)?/.source.replace( 'WC', _wordChar );\r\n\r\n\t// Property and accessor. May not contain reserved characters. Accessor may\r\n\t// contain any non-bracket characters.\r\n\tvar _propertyRe = /\\.(WC+)(?:\\[(.+)\\])?/.source.replace( 'WC', _wordChar );\r\n\r\n\tvar _trackRe = new RegExp( ''\r\n\t\t+ '^'\r\n\t\t+ _directoryRe\r\n\t\t+ _nodeRe\r\n\t\t+ _objectRe\r\n\t\t+ _propertyRe\r\n\t\t+ '$'\r\n\t);\r\n\r\n\tvar _supportedObjectNames = [ 'material', 'materials', 'bones' ];\r\n\r\n\tfunction Composite( targetGroup, path, optionalParsedPath ) {\r\n\r\n\t\tvar parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );\r\n\r\n\t\tthis._targetGroup = targetGroup;\r\n\t\tthis._bindings = targetGroup.subscribe_( path, parsedPath );\r\n\r\n\t}\r\n\r\n\tObject.assign( Composite.prototype, {\r\n\r\n\t\tgetValue: function ( array, offset ) {\r\n\r\n\t\t\tthis.bind(); // bind all binding\r\n\r\n\t\t\tvar firstValidIndex = this._targetGroup.nCachedObjects_,\r\n\t\t\t\tbinding = this._bindings[ firstValidIndex ];\r\n\r\n\t\t\t// and only call .getValue on the first\r\n\t\t\tif ( binding !== undefined ) { binding.getValue( array, offset ); }\r\n\r\n\t\t},\r\n\r\n\t\tsetValue: function ( array, offset ) {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].setValue( array, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tbind: function () {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].bind();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tunbind: function () {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].unbind();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\r\n\tfunction PropertyBinding( rootNode, path, parsedPath ) {\r\n\r\n\t\tthis.path = path;\r\n\t\tthis.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );\r\n\r\n\t\tthis.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;\r\n\r\n\t\tthis.rootNode = rootNode;\r\n\r\n\t}\r\n\r\n\tObject.assign( PropertyBinding, {\r\n\r\n\t\tComposite: Composite,\r\n\r\n\t\tcreate: function ( root, path, parsedPath ) {\r\n\r\n\t\t\tif ( ! ( root && root.isAnimationObjectGroup ) ) {\r\n\r\n\t\t\t\treturn new PropertyBinding( root, path, parsedPath );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn new PropertyBinding.Composite( root, path, parsedPath );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Replaces spaces with underscores and removes unsupported characters from\r\n\t\t * node names, to ensure compatibility with parseTrackName().\r\n\t\t *\r\n\t\t * @param {string} name Node name to be sanitized.\r\n\t\t * @return {string}\r\n\t\t */\r\n\t\tsanitizeNodeName: function ( name ) {\r\n\r\n\t\t\treturn name.replace( /\\s/g, '_' ).replace( _reservedRe, '' );\r\n\r\n\t\t},\r\n\r\n\t\tparseTrackName: function ( trackName ) {\r\n\r\n\t\t\tvar matches = _trackRe.exec( trackName );\r\n\r\n\t\t\tif ( ! matches ) {\r\n\r\n\t\t\t\tthrow new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar results = {\r\n\t\t\t\t// directoryName: matches[ 1 ], // (tschw) currently unused\r\n\t\t\t\tnodeName: matches[ 2 ],\r\n\t\t\t\tobjectName: matches[ 3 ],\r\n\t\t\t\tobjectIndex: matches[ 4 ],\r\n\t\t\t\tpropertyName: matches[ 5 ], // required\r\n\t\t\t\tpropertyIndex: matches[ 6 ]\r\n\t\t\t};\r\n\r\n\t\t\tvar lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );\r\n\r\n\t\t\tif ( lastDot !== undefined && lastDot !== - 1 ) {\r\n\r\n\t\t\t\tvar objectName = results.nodeName.substring( lastDot + 1 );\r\n\r\n\t\t\t\t// Object names must be checked against a whitelist. Otherwise, there\r\n\t\t\t\t// is no way to parse 'foo.bar.baz': 'baz' must be a property, but\r\n\t\t\t\t// 'bar' could be the objectName, or part of a nodeName (which can\r\n\t\t\t\t// include '.' characters).\r\n\t\t\t\tif ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {\r\n\r\n\t\t\t\t\tresults.nodeName = results.nodeName.substring( 0, lastDot );\r\n\t\t\t\t\tresults.objectName = objectName;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( results.propertyName === null || results.propertyName.length === 0 ) {\r\n\r\n\t\t\t\tthrow new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn results;\r\n\r\n\t\t},\r\n\r\n\t\tfindNode: function ( root, nodeName ) {\r\n\r\n\t\t\tif ( ! nodeName || nodeName === \"\" || nodeName === \"root\" || nodeName === \".\" || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {\r\n\r\n\t\t\t\treturn root;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// search into skeleton bones.\r\n\t\t\tif ( root.skeleton ) {\r\n\r\n\t\t\t\tvar bone = root.skeleton.getBoneByName( nodeName );\r\n\r\n\t\t\t\tif ( bone !== undefined ) {\r\n\r\n\t\t\t\t\treturn bone;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// search into node subtree.\r\n\t\t\tif ( root.children ) {\r\n\r\n\t\t\t\tvar searchNodeSubtree = function ( children ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < children.length; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar childNode = children[ i ];\r\n\r\n\t\t\t\t\t\tif ( childNode.name === nodeName || childNode.uuid === nodeName ) {\r\n\r\n\t\t\t\t\t\t\treturn childNode;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar result = searchNodeSubtree( childNode.children );\r\n\r\n\t\t\t\t\t\tif ( result ) { return result; }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar subTreeNode = searchNodeSubtree( root.children );\r\n\r\n\t\t\t\tif ( subTreeNode ) {\r\n\r\n\t\t\t\t\treturn subTreeNode;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( PropertyBinding.prototype, { // prototype, continued\r\n\r\n\t\t// these are used to \"bind\" a nonexistent property\r\n\t\t_getValue_unavailable: function () {},\r\n\t\t_setValue_unavailable: function () {},\r\n\r\n\t\tBindingType: {\r\n\t\t\tDirect: 0,\r\n\t\t\tEntireArray: 1,\r\n\t\t\tArrayElement: 2,\r\n\t\t\tHasFromToArray: 3\r\n\t\t},\r\n\r\n\t\tVersioning: {\r\n\t\t\tNone: 0,\r\n\t\t\tNeedsUpdate: 1,\r\n\t\t\tMatrixWorldNeedsUpdate: 2\r\n\t\t},\r\n\r\n\t\tGetterByBindingType: [\r\n\r\n\t\t\tfunction getValue_direct( buffer, offset ) {\r\n\r\n\t\t\t\tbuffer[ offset ] = this.node[ this.propertyName ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_array( buffer, offset ) {\r\n\r\n\t\t\t\tvar source = this.resolvedProperty;\r\n\r\n\t\t\t\tfor ( var i = 0, n = source.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ offset ++ ] = source[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_arrayElement( buffer, offset ) {\r\n\r\n\t\t\t\tbuffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_toArray( buffer, offset ) {\r\n\r\n\t\t\t\tthis.resolvedProperty.toArray( buffer, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t],\r\n\r\n\t\tSetterByBindingTypeAndVersioning: [\r\n\r\n\t\t\t[\r\n\t\t\t\t// Direct\r\n\r\n\t\t\t\tfunction setValue_direct( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_direct_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// EntireArray\r\n\r\n\t\t\t\tfunction setValue_array( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_array_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// ArrayElement\r\n\r\n\t\t\t\tfunction setValue_arrayElement( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_arrayElement_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// HasToFromArray\r\n\r\n\t\t\t\tfunction setValue_fromArray( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_fromArray_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t]\r\n\r\n\t\t],\r\n\r\n\t\tgetValue: function getValue_unbound( targetArray, offset ) {\r\n\r\n\t\t\tthis.bind();\r\n\t\t\tthis.getValue( targetArray, offset );\r\n\r\n\t\t\t// Note: This class uses a State pattern on a per-method basis:\r\n\t\t\t// 'bind' sets 'this.getValue' / 'setValue' and shadows the\r\n\t\t\t// prototype version of these methods with one that represents\r\n\t\t\t// the bound state. When the property is not found, the methods\r\n\t\t\t// become no-ops.\r\n\r\n\t\t},\r\n\r\n\t\tsetValue: function getValue_unbound( sourceArray, offset ) {\r\n\r\n\t\t\tthis.bind();\r\n\t\t\tthis.setValue( sourceArray, offset );\r\n\r\n\t\t},\r\n\r\n\t\t// create getter / setter pair for a property in the scene graph\r\n\t\tbind: function () {\r\n\r\n\t\t\tvar targetObject = this.node,\r\n\t\t\t\tparsedPath = this.parsedPath,\r\n\r\n\t\t\t\tobjectName = parsedPath.objectName,\r\n\t\t\t\tpropertyName = parsedPath.propertyName,\r\n\t\t\t\tpropertyIndex = parsedPath.propertyIndex;\r\n\r\n\t\t\tif ( ! targetObject ) {\r\n\r\n\t\t\t\ttargetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;\r\n\r\n\t\t\t\tthis.node = targetObject;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// set fail state so we can just 'return' on error\r\n\t\t\tthis.getValue = this._getValue_unavailable;\r\n\t\t\tthis.setValue = this._setValue_unavailable;\r\n\r\n\t\t\t// ensure there is a value node\r\n\t\t\tif ( ! targetObject ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\\'t found.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( objectName ) {\r\n\r\n\t\t\t\tvar objectIndex = parsedPath.objectIndex;\r\n\r\n\t\t\t\t// special cases were we need to reach deeper into the hierarchy to get the face materials....\r\n\t\t\t\tswitch ( objectName ) {\r\n\r\n\t\t\t\t\tcase 'materials':\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.material ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.material.materials ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject.material.materials;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'bones':\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.skeleton ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// potential future optimization: skip this if propertyIndex is already an integer\r\n\t\t\t\t\t\t// and convert the integer string to a true integer.\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject.skeleton.bones;\r\n\r\n\t\t\t\t\t\t// support resolving morphTarget names into indices.\r\n\t\t\t\t\t\tfor ( var i = 0; i < targetObject.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject[ i ].name === objectIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tobjectIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\tif ( targetObject[ objectName ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject[ objectName ];\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tif ( objectIndex !== undefined ) {\r\n\r\n\t\t\t\t\tif ( targetObject[ objectIndex ] === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttargetObject = targetObject[ objectIndex ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// resolve property\r\n\t\t\tvar nodeProperty = targetObject[ propertyName ];\r\n\r\n\t\t\tif ( nodeProperty === undefined ) {\r\n\r\n\t\t\t\tvar nodeName = parsedPath.nodeName;\r\n\r\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +\r\n\t\t\t\t\t'.' + propertyName + ' but it wasn\\'t found.', targetObject );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// determine versioning scheme\r\n\t\t\tvar versioning = this.Versioning.None;\r\n\r\n\t\t\tthis.targetObject = targetObject;\r\n\r\n\t\t\tif ( targetObject.needsUpdate !== undefined ) { // material\r\n\r\n\t\t\t\tversioning = this.Versioning.NeedsUpdate;\r\n\r\n\t\t\t} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform\r\n\r\n\t\t\t\tversioning = this.Versioning.MatrixWorldNeedsUpdate;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// determine how the property gets bound\r\n\t\t\tvar bindingType = this.BindingType.Direct;\r\n\r\n\t\t\tif ( propertyIndex !== undefined ) {\r\n\r\n\t\t\t\t// access a sub element of the property array (only primitives are supported right now)\r\n\r\n\t\t\t\tif ( propertyName === \"morphTargetInfluences\" ) {\r\n\r\n\t\t\t\t\t// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.\r\n\r\n\t\t\t\t\t// support resolving morphTarget names into indices.\r\n\t\t\t\t\tif ( ! targetObject.geometry ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( targetObject.geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphAttributes ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tpropertyIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphTargets ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tpropertyIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbindingType = this.BindingType.ArrayElement;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\t\t\t\tthis.propertyIndex = propertyIndex;\r\n\r\n\t\t\t} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {\r\n\r\n\t\t\t\t// must use copy for Object3D.Euler/Quaternion\r\n\r\n\t\t\t\tbindingType = this.BindingType.HasFromToArray;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\r\n\t\t\t} else if ( Array.isArray( nodeProperty ) ) {\r\n\r\n\t\t\t\tbindingType = this.BindingType.EntireArray;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.propertyName = propertyName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// select getter / setter\r\n\t\t\tthis.getValue = this.GetterByBindingType[ bindingType ];\r\n\t\t\tthis.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];\r\n\r\n\t\t},\r\n\r\n\t\tunbind: function () {\r\n\r\n\t\t\tthis.node = null;\r\n\r\n\t\t\t// back to the prototype version of getValue / setValue\r\n\t\t\t// note: avoiding to mutate the shape of 'this' via 'delete'\r\n\t\t\tthis.getValue = this._getValue_unbound;\r\n\t\t\tthis.setValue = this._setValue_unbound;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//!\\ DECLARE ALIAS AFTER assign prototype !\r\n\tObject.assign( PropertyBinding.prototype, {\r\n\r\n\t\t// initial state of these methods that calls 'bind'\r\n\t\t_getValue_unbound: PropertyBinding.prototype.getValue,\r\n\t\t_setValue_unbound: PropertyBinding.prototype.setValue,\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A group of objects that receives a shared animation state.\r\n\t *\r\n\t * Usage:\r\n\t *\r\n\t * - Add objects you would otherwise pass as 'root' to the\r\n\t * constructor or the .clipAction method of AnimationMixer.\r\n\t *\r\n\t * - Instead pass this object as 'root'.\r\n\t *\r\n\t * - You can also add and remove objects later when the mixer\r\n\t * is running.\r\n\t *\r\n\t * Note:\r\n\t *\r\n\t * Objects of this class appear as one object to the mixer,\r\n\t * so cache control of the individual objects must be done\r\n\t * on the group.\r\n\t *\r\n\t * Limitation:\r\n\t *\r\n\t * - The animated properties must be compatible among the\r\n\t * all objects in the group.\r\n\t *\r\n\t * - A single property can either be controlled through a\r\n\t * target group or directly, but not both.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction AnimationObjectGroup() {\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\t// cached objects followed by the active ones\r\n\t\tthis._objects = Array.prototype.slice.call( arguments );\r\n\r\n\t\tthis.nCachedObjects_ = 0; // threshold\r\n\t\t// note: read by PropertyBinding.Composite\r\n\r\n\t\tvar indices = {};\r\n\t\tthis._indicesByUUID = indices; // for bookkeeping\r\n\r\n\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\tindices[ arguments[ i ].uuid ] = i;\r\n\r\n\t\t}\r\n\r\n\t\tthis._paths = []; // inside: string\r\n\t\tthis._parsedPaths = []; // inside: { we don't care, here }\r\n\t\tthis._bindings = []; // inside: Array< PropertyBinding >\r\n\t\tthis._bindingsIndicesByPath = {}; // inside: indices in these arrays\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tthis.stats = {\r\n\r\n\t\t\tobjects: {\r\n\t\t\t\tget total() {\r\n\r\n\t\t\t\t\treturn scope._objects.length;\r\n\r\n\t\t\t\t},\r\n\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\treturn this.total - scope.nCachedObjects_;\r\n\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tget bindingsPerObject() {\r\n\r\n\t\t\t\treturn scope._bindings.length;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationObjectGroup.prototype, {\r\n\r\n\t\tisAnimationObjectGroup: true,\r\n\r\n\t\tadd: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tpaths = this._paths,\r\n\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length,\r\n\t\t\t\tknownObject = undefined;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index === undefined ) {\r\n\r\n\t\t\t\t\t// unknown object -> add it to the ACTIVE region\r\n\r\n\t\t\t\t\tindex = nObjects ++;\r\n\t\t\t\t\tindicesByUUID[ uuid ] = index;\r\n\t\t\t\t\tobjects.push( object );\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tbindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( index < nCachedObjects ) {\r\n\r\n\t\t\t\t\tknownObject = objects[ index ];\r\n\r\n\t\t\t\t\t// move existing object to the ACTIVE region\r\n\r\n\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\r\n\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ];\r\n\r\n\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\r\n\t\t\t\t\tobjects[ index ] = lastCachedObject;\r\n\r\n\t\t\t\t\tindicesByUUID[ uuid ] = firstActiveIndex;\r\n\t\t\t\t\tobjects[ firstActiveIndex ] = object;\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\r\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\r\n\r\n\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\r\n\r\n\t\t\t\t\t\tif ( binding === undefined ) {\r\n\r\n\t\t\t\t\t\t\t// since we do not bother to create new bindings\r\n\t\t\t\t\t\t\t// for objects that are cached, the binding may\r\n\t\t\t\t\t\t\t// or may not exist\r\n\r\n\t\t\t\t\t\t\tbinding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = binding;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( objects[ index ] !== knownObject ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +\r\n\t\t\t\t\t\t'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );\r\n\r\n\t\t\t\t} // else the object is already where we want it to be\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\tremove: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index !== undefined && index >= nCachedObjects ) {\r\n\r\n\t\t\t\t\t// move existing object into the CACHED region\r\n\r\n\t\t\t\t\tvar lastCachedIndex = nCachedObjects ++,\r\n\t\t\t\t\t\tfirstActiveObject = objects[ lastCachedIndex ];\r\n\r\n\t\t\t\t\tindicesByUUID[ firstActiveObject.uuid ] = index;\r\n\t\t\t\t\tobjects[ index ] = firstActiveObject;\r\n\r\n\t\t\t\t\tindicesByUUID[ uuid ] = lastCachedIndex;\r\n\t\t\t\t\tobjects[ lastCachedIndex ] = object;\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\tfirstActive = bindingsForPath[ lastCachedIndex ],\r\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\r\n\r\n\t\t\t\t\t\tbindingsForPath[ index ] = firstActive;\r\n\t\t\t\t\t\tbindingsForPath[ lastCachedIndex ] = binding;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\t// remove & forget\r\n\t\tuncache: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\t\tdelete indicesByUUID[ uuid ];\r\n\r\n\t\t\t\t\tif ( index < nCachedObjects ) {\r\n\r\n\t\t\t\t\t\t// object is cached, shrink the CACHED region\r\n\r\n\t\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\r\n\t\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ],\r\n\t\t\t\t\t\t\tlastIndex = -- nObjects,\r\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\r\n\r\n\t\t\t\t\t\t// last cached object takes this object's place\r\n\t\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\r\n\t\t\t\t\t\tobjects[ index ] = lastCachedObject;\r\n\r\n\t\t\t\t\t\t// last object goes to the activated slot and pop\r\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = firstActiveIndex;\r\n\t\t\t\t\t\tobjects[ firstActiveIndex ] = lastObject;\r\n\t\t\t\t\t\tobjects.pop();\r\n\r\n\t\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\r\n\t\t\t\t\t\t\t\tlast = bindingsForPath[ lastIndex ];\r\n\r\n\t\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\r\n\t\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = last;\r\n\t\t\t\t\t\t\tbindingsForPath.pop();\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// object is active, just swap with the last and pop\r\n\r\n\t\t\t\t\t\tvar lastIndex = -- nObjects,\r\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\r\n\r\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = index;\r\n\t\t\t\t\t\tobjects[ index ] = lastObject;\r\n\t\t\t\t\t\tobjects.pop();\r\n\r\n\t\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ];\r\n\r\n\t\t\t\t\t\t\tbindingsForPath[ index ] = bindingsForPath[ lastIndex ];\r\n\t\t\t\t\t\t\tbindingsForPath.pop();\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} // cached or active\r\n\r\n\t\t\t\t} // if object is known\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\t// Internal interface used by befriended PropertyBinding.Composite:\r\n\r\n\t\tsubscribe_: function ( path, parsedPath ) {\r\n\r\n\t\t\t// returns an array of bindings for the given path that is changed\r\n\t\t\t// according to the contained objects in the group\r\n\r\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\r\n\t\t\t\tindex = indicesByPath[ path ],\r\n\t\t\t\tbindings = this._bindings;\r\n\r\n\t\t\tif ( index !== undefined ) { return bindings[ index ]; }\r\n\r\n\t\t\tvar paths = this._paths,\r\n\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\tobjects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tbindingsForPath = new Array( nObjects );\r\n\r\n\t\t\tindex = bindings.length;\r\n\r\n\t\t\tindicesByPath[ path ] = index;\r\n\r\n\t\t\tpaths.push( path );\r\n\t\t\tparsedPaths.push( parsedPath );\r\n\t\t\tbindings.push( bindingsForPath );\r\n\r\n\t\t\tfor ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = objects[ i ];\r\n\t\t\t\tbindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn bindingsForPath;\r\n\r\n\t\t},\r\n\r\n\t\tunsubscribe_: function ( path ) {\r\n\r\n\t\t\t// tells the group to forget about a property path and no longer\r\n\t\t\t// update the array previously obtained with 'subscribe_'\r\n\r\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\r\n\t\t\t\tindex = indicesByPath[ path ];\r\n\r\n\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\tvar paths = this._paths,\r\n\t\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\t\tbindings = this._bindings,\r\n\t\t\t\t\tlastBindingsIndex = bindings.length - 1,\r\n\t\t\t\t\tlastBindings = bindings[ lastBindingsIndex ],\r\n\t\t\t\t\tlastBindingsPath = path[ lastBindingsIndex ];\r\n\r\n\t\t\t\tindicesByPath[ lastBindingsPath ] = index;\r\n\r\n\t\t\t\tbindings[ index ] = lastBindings;\r\n\t\t\t\tbindings.pop();\r\n\r\n\t\t\t\tparsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];\r\n\t\t\t\tparsedPaths.pop();\r\n\r\n\t\t\t\tpaths[ index ] = paths[ lastBindingsIndex ];\r\n\t\t\t\tpaths.pop();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Action provided by AnimationMixer for scheduling clip playback on specific\r\n\t * objects.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t *\r\n\t */\r\n\r\n\tfunction AnimationAction( mixer, clip, localRoot ) {\r\n\r\n\t\tthis._mixer = mixer;\r\n\t\tthis._clip = clip;\r\n\t\tthis._localRoot = localRoot || null;\r\n\r\n\t\tvar tracks = clip.tracks,\r\n\t\t\tnTracks = tracks.length,\r\n\t\t\tinterpolants = new Array( nTracks );\r\n\r\n\t\tvar interpolantSettings = {\r\n\t\t\tendingStart: ZeroCurvatureEnding,\r\n\t\t\tendingEnd: ZeroCurvatureEnding\r\n\t\t};\r\n\r\n\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\r\n\r\n\t\t\tvar interpolant = tracks[ i ].createInterpolant( null );\r\n\t\t\tinterpolants[ i ] = interpolant;\r\n\t\t\tinterpolant.settings = interpolantSettings;\r\n\r\n\t\t}\r\n\r\n\t\tthis._interpolantSettings = interpolantSettings;\r\n\r\n\t\tthis._interpolants = interpolants; // bound by the mixer\r\n\r\n\t\t// inside: PropertyMixer (managed by the mixer)\r\n\t\tthis._propertyBindings = new Array( nTracks );\r\n\r\n\t\tthis._cacheIndex = null; // for the memory manager\r\n\t\tthis._byClipCacheIndex = null; // for the memory manager\r\n\r\n\t\tthis._timeScaleInterpolant = null;\r\n\t\tthis._weightInterpolant = null;\r\n\r\n\t\tthis.loop = LoopRepeat;\r\n\t\tthis._loopCount = - 1;\r\n\r\n\t\t// global mixer time when the action is to be started\r\n\t\t// it's set back to 'null' upon start of the action\r\n\t\tthis._startTime = null;\r\n\r\n\t\t// scaled local time of the action\r\n\t\t// gets clamped or wrapped to 0..clip.duration according to loop\r\n\t\tthis.time = 0;\r\n\r\n\t\tthis.timeScale = 1;\r\n\t\tthis._effectiveTimeScale = 1;\r\n\r\n\t\tthis.weight = 1;\r\n\t\tthis._effectiveWeight = 1;\r\n\r\n\t\tthis.repetitions = Infinity; // no. of repetitions when looping\r\n\r\n\t\tthis.paused = false; // true -> zero effective time scale\r\n\t\tthis.enabled = true; // false -> zero effective weight\r\n\r\n\t\tthis.clampWhenFinished = false;// keep feeding the last frame?\r\n\r\n\t\tthis.zeroSlopeAtStart = true;// for smooth interpolation w/o separate\r\n\t\tthis.zeroSlopeAtEnd = true;// clips for start, loop and end\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationAction.prototype, {\r\n\r\n\t\t// State & Scheduling\r\n\r\n\t\tplay: function () {\r\n\r\n\t\t\tthis._mixer._activateAction( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tthis._mixer._deactivateAction( this );\r\n\r\n\t\t\treturn this.reset();\r\n\r\n\t\t},\r\n\r\n\t\treset: function () {\r\n\r\n\t\t\tthis.paused = false;\r\n\t\t\tthis.enabled = true;\r\n\r\n\t\t\tthis.time = 0; // restart clip\r\n\t\t\tthis._loopCount = - 1;// forget previous loops\r\n\t\t\tthis._startTime = null;// forget scheduling\r\n\r\n\t\t\treturn this.stopFading().stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\tisRunning: function () {\r\n\r\n\t\t\treturn this.enabled && ! this.paused && this.timeScale !== 0 &&\r\n\t\t\t\tthis._startTime === null && this._mixer._isActiveAction( this );\r\n\r\n\t\t},\r\n\r\n\t\t// return true when play has been called\r\n\t\tisScheduled: function () {\r\n\r\n\t\t\treturn this._mixer._isActiveAction( this );\r\n\r\n\t\t},\r\n\r\n\t\tstartAt: function ( time ) {\r\n\r\n\t\t\tthis._startTime = time;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoop: function ( mode, repetitions ) {\r\n\r\n\t\t\tthis.loop = mode;\r\n\t\t\tthis.repetitions = repetitions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Weight\r\n\r\n\t\t// set the weight stopping any scheduled fading\r\n\t\t// although .enabled = false yields an effective weight of zero, this\r\n\t\t// method does *not* change .enabled, because it would be confusing\r\n\t\tsetEffectiveWeight: function ( weight ) {\r\n\r\n\t\t\tthis.weight = weight;\r\n\r\n\t\t\t// note: same logic as when updated at runtime\r\n\t\t\tthis._effectiveWeight = this.enabled ? weight : 0;\r\n\r\n\t\t\treturn this.stopFading();\r\n\r\n\t\t},\r\n\r\n\t\t// return the weight considering fading and .enabled\r\n\t\tgetEffectiveWeight: function () {\r\n\r\n\t\t\treturn this._effectiveWeight;\r\n\r\n\t\t},\r\n\r\n\t\tfadeIn: function ( duration ) {\r\n\r\n\t\t\treturn this._scheduleFading( duration, 0, 1 );\r\n\r\n\t\t},\r\n\r\n\t\tfadeOut: function ( duration ) {\r\n\r\n\t\t\treturn this._scheduleFading( duration, 1, 0 );\r\n\r\n\t\t},\r\n\r\n\t\tcrossFadeFrom: function ( fadeOutAction, duration, warp ) {\r\n\r\n\t\t\tfadeOutAction.fadeOut( duration );\r\n\t\t\tthis.fadeIn( duration );\r\n\r\n\t\t\tif ( warp ) {\r\n\r\n\t\t\t\tvar fadeInDuration = this._clip.duration,\r\n\t\t\t\t\tfadeOutDuration = fadeOutAction._clip.duration,\r\n\r\n\t\t\t\t\tstartEndRatio = fadeOutDuration / fadeInDuration,\r\n\t\t\t\t\tendStartRatio = fadeInDuration / fadeOutDuration;\r\n\r\n\t\t\t\tfadeOutAction.warp( 1.0, startEndRatio, duration );\r\n\t\t\t\tthis.warp( endStartRatio, 1.0, duration );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcrossFadeTo: function ( fadeInAction, duration, warp ) {\r\n\r\n\t\t\treturn fadeInAction.crossFadeFrom( this, duration, warp );\r\n\r\n\t\t},\r\n\r\n\t\tstopFading: function () {\r\n\r\n\t\t\tvar weightInterpolant = this._weightInterpolant;\r\n\r\n\t\t\tif ( weightInterpolant !== null ) {\r\n\r\n\t\t\t\tthis._weightInterpolant = null;\r\n\t\t\t\tthis._mixer._takeBackControlInterpolant( weightInterpolant );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Time Scale Control\r\n\r\n\t\t// set the time scale stopping any scheduled warping\r\n\t\t// although .paused = true yields an effective time scale of zero, this\r\n\t\t// method does *not* change .paused, because it would be confusing\r\n\t\tsetEffectiveTimeScale: function ( timeScale ) {\r\n\r\n\t\t\tthis.timeScale = timeScale;\r\n\t\t\tthis._effectiveTimeScale = this.paused ? 0 : timeScale;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\t// return the time scale considering warping and .paused\r\n\t\tgetEffectiveTimeScale: function () {\r\n\r\n\t\t\treturn this._effectiveTimeScale;\r\n\r\n\t\t},\r\n\r\n\t\tsetDuration: function ( duration ) {\r\n\r\n\t\t\tthis.timeScale = this._clip.duration / duration;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\tsyncWith: function ( action ) {\r\n\r\n\t\t\tthis.time = action.time;\r\n\t\t\tthis.timeScale = action.timeScale;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\thalt: function ( duration ) {\r\n\r\n\t\t\treturn this.warp( this._effectiveTimeScale, 0, duration );\r\n\r\n\t\t},\r\n\r\n\t\twarp: function ( startTimeScale, endTimeScale, duration ) {\r\n\r\n\t\t\tvar mixer = this._mixer, now = mixer.time,\r\n\t\t\t\tinterpolant = this._timeScaleInterpolant,\r\n\r\n\t\t\t\ttimeScale = this.timeScale;\r\n\r\n\t\t\tif ( interpolant === null ) {\r\n\r\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\r\n\t\t\t\tthis._timeScaleInterpolant = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = interpolant.parameterPositions,\r\n\t\t\t\tvalues = interpolant.sampleValues;\r\n\r\n\t\t\ttimes[ 0 ] = now;\r\n\t\t\ttimes[ 1 ] = now + duration;\r\n\r\n\t\t\tvalues[ 0 ] = startTimeScale / timeScale;\r\n\t\t\tvalues[ 1 ] = endTimeScale / timeScale;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstopWarping: function () {\r\n\r\n\t\t\tvar timeScaleInterpolant = this._timeScaleInterpolant;\r\n\r\n\t\t\tif ( timeScaleInterpolant !== null ) {\r\n\r\n\t\t\t\tthis._timeScaleInterpolant = null;\r\n\t\t\t\tthis._mixer._takeBackControlInterpolant( timeScaleInterpolant );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Object Accessors\r\n\r\n\t\tgetMixer: function () {\r\n\r\n\t\t\treturn this._mixer;\r\n\r\n\t\t},\r\n\r\n\t\tgetClip: function () {\r\n\r\n\t\t\treturn this._clip;\r\n\r\n\t\t},\r\n\r\n\t\tgetRoot: function () {\r\n\r\n\t\t\treturn this._localRoot || this._mixer._root;\r\n\r\n\t\t},\r\n\r\n\t\t// Interna\r\n\r\n\t\t_update: function ( time, deltaTime, timeDirection, accuIndex ) {\r\n\r\n\t\t\t// called by the mixer\r\n\r\n\t\t\tif ( ! this.enabled ) {\r\n\r\n\t\t\t\t// call ._updateWeight() to update ._effectiveWeight\r\n\r\n\t\t\t\tthis._updateWeight( time );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar startTime = this._startTime;\r\n\r\n\t\t\tif ( startTime !== null ) {\r\n\r\n\t\t\t\t// check for scheduled start of action\r\n\r\n\t\t\t\tvar timeRunning = ( time - startTime ) * timeDirection;\r\n\t\t\t\tif ( timeRunning < 0 || timeDirection === 0 ) {\r\n\r\n\t\t\t\t\treturn; // yet to come / don't decide when delta = 0\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// start\r\n\r\n\t\t\t\tthis._startTime = null; // unschedule\r\n\t\t\t\tdeltaTime = timeDirection * timeRunning;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// apply time scale and advance time\r\n\r\n\t\t\tdeltaTime *= this._updateTimeScale( time );\r\n\t\t\tvar clipTime = this._updateTime( deltaTime );\r\n\r\n\t\t\t// note: _updateTime may disable the action resulting in\r\n\t\t\t// an effective weight of 0\r\n\r\n\t\t\tvar weight = this._updateWeight( time );\r\n\r\n\t\t\tif ( weight > 0 ) {\r\n\r\n\t\t\t\tvar interpolants = this._interpolants;\r\n\t\t\t\tvar propertyMixers = this._propertyBindings;\r\n\r\n\t\t\t\tfor ( var j = 0, m = interpolants.length; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\tinterpolants[ j ].evaluate( clipTime );\r\n\t\t\t\t\tpropertyMixers[ j ].accumulate( accuIndex, weight );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_updateWeight: function ( time ) {\r\n\r\n\t\t\tvar weight = 0;\r\n\r\n\t\t\tif ( this.enabled ) {\r\n\r\n\t\t\t\tweight = this.weight;\r\n\t\t\t\tvar interpolant = this._weightInterpolant;\r\n\r\n\t\t\t\tif ( interpolant !== null ) {\r\n\r\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\r\n\r\n\t\t\t\t\tweight *= interpolantValue;\r\n\r\n\t\t\t\t\tif ( time > interpolant.parameterPositions[ 1 ] ) {\r\n\r\n\t\t\t\t\t\tthis.stopFading();\r\n\r\n\t\t\t\t\t\tif ( interpolantValue === 0 ) {\r\n\r\n\t\t\t\t\t\t\t// faded out, disable\r\n\t\t\t\t\t\t\tthis.enabled = false;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._effectiveWeight = weight;\r\n\t\t\treturn weight;\r\n\r\n\t\t},\r\n\r\n\t\t_updateTimeScale: function ( time ) {\r\n\r\n\t\t\tvar timeScale = 0;\r\n\r\n\t\t\tif ( ! this.paused ) {\r\n\r\n\t\t\t\ttimeScale = this.timeScale;\r\n\r\n\t\t\t\tvar interpolant = this._timeScaleInterpolant;\r\n\r\n\t\t\t\tif ( interpolant !== null ) {\r\n\r\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\r\n\r\n\t\t\t\t\ttimeScale *= interpolantValue;\r\n\r\n\t\t\t\t\tif ( time > interpolant.parameterPositions[ 1 ] ) {\r\n\r\n\t\t\t\t\t\tthis.stopWarping();\r\n\r\n\t\t\t\t\t\tif ( timeScale === 0 ) {\r\n\r\n\t\t\t\t\t\t\t// motion has halted, pause\r\n\t\t\t\t\t\t\tthis.paused = true;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t// warp done - apply final time scale\r\n\t\t\t\t\t\t\tthis.timeScale = timeScale;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._effectiveTimeScale = timeScale;\r\n\t\t\treturn timeScale;\r\n\r\n\t\t},\r\n\r\n\t\t_updateTime: function ( deltaTime ) {\r\n\r\n\t\t\tvar time = this.time + deltaTime;\r\n\t\t\tvar duration = this._clip.duration;\r\n\t\t\tvar loop = this.loop;\r\n\t\t\tvar loopCount = this._loopCount;\r\n\r\n\t\t\tvar pingPong = ( loop === LoopPingPong );\r\n\r\n\t\t\tif ( deltaTime === 0 ) {\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) { return time; }\r\n\r\n\t\t\t\treturn ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( loop === LoopOnce ) {\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) {\r\n\r\n\t\t\t\t\t// just started\r\n\r\n\t\t\t\t\tthis._loopCount = 0;\r\n\t\t\t\t\tthis._setEndings( true, true, false );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\thandle_stop: {\r\n\r\n\t\t\t\t\tif ( time >= duration ) {\r\n\r\n\t\t\t\t\t\ttime = duration;\r\n\r\n\t\t\t\t\t} else if ( time < 0 ) {\r\n\r\n\t\t\t\t\t\ttime = 0;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tbreak handle_stop;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( this.clampWhenFinished ) { this.paused = true; }\r\n\t\t\t\t\telse { this.enabled = false; }\r\n\r\n\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\ttype: 'finished', action: this,\r\n\t\t\t\t\t\tdirection: deltaTime < 0 ? - 1 : 1\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else { // repetitive Repeat or PingPong\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) {\r\n\r\n\t\t\t\t\t// just started\r\n\r\n\t\t\t\t\tif ( deltaTime >= 0 ) {\r\n\r\n\t\t\t\t\t\tloopCount = 0;\r\n\r\n\t\t\t\t\t\tthis._setEndings( true, this.repetitions === 0, pingPong );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// when looping in reverse direction, the initial\r\n\t\t\t\t\t\t// transition through zero counts as a repetition,\r\n\t\t\t\t\t\t// so leave loopCount at -1\r\n\r\n\t\t\t\t\t\tthis._setEndings( this.repetitions === 0, true, pingPong );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( time >= duration || time < 0 ) {\r\n\r\n\t\t\t\t\t// wrap around\r\n\r\n\t\t\t\t\tvar loopDelta = Math.floor( time / duration ); // signed\r\n\t\t\t\t\ttime -= duration * loopDelta;\r\n\r\n\t\t\t\t\tloopCount += Math.abs( loopDelta );\r\n\r\n\t\t\t\t\tvar pending = this.repetitions - loopCount;\r\n\r\n\t\t\t\t\tif ( pending <= 0 ) {\r\n\r\n\t\t\t\t\t\t// have to stop (switch state, clamp time, fire event)\r\n\r\n\t\t\t\t\t\tif ( this.clampWhenFinished ) { this.paused = true; }\r\n\t\t\t\t\t\telse { this.enabled = false; }\r\n\r\n\t\t\t\t\t\ttime = deltaTime > 0 ? duration : 0;\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\t\ttype: 'finished', action: this,\r\n\t\t\t\t\t\t\tdirection: deltaTime > 0 ? 1 : - 1\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// keep running\r\n\r\n\t\t\t\t\t\tif ( pending === 1 ) {\r\n\r\n\t\t\t\t\t\t\t// entering the last round\r\n\r\n\t\t\t\t\t\t\tvar atStart = deltaTime < 0;\r\n\t\t\t\t\t\t\tthis._setEndings( atStart, ! atStart, pingPong );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tthis._setEndings( false, false, pingPong );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis._loopCount = loopCount;\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\t\ttype: 'loop', action: this, loopDelta: loopDelta\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( pingPong && ( loopCount & 1 ) === 1 ) {\r\n\r\n\t\t\t\t\t// invert time for the \"pong round\"\r\n\r\n\t\t\t\t\treturn duration - time;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn time;\r\n\r\n\t\t},\r\n\r\n\t\t_setEndings: function ( atStart, atEnd, pingPong ) {\r\n\r\n\t\t\tvar settings = this._interpolantSettings;\r\n\r\n\t\t\tif ( pingPong ) {\r\n\r\n\t\t\t\tsettings.endingStart = ZeroSlopeEnding;\r\n\t\t\t\tsettings.endingEnd = ZeroSlopeEnding;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// assuming for LoopOnce atStart == atEnd == true\r\n\r\n\t\t\t\tif ( atStart ) {\r\n\r\n\t\t\t\t\tsettings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tsettings.endingStart = WrapAroundEnding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( atEnd ) {\r\n\r\n\t\t\t\t\tsettings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tsettings.endingEnd \t = WrapAroundEnding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_scheduleFading: function ( duration, weightNow, weightThen ) {\r\n\r\n\t\t\tvar mixer = this._mixer, now = mixer.time,\r\n\t\t\t\tinterpolant = this._weightInterpolant;\r\n\r\n\t\t\tif ( interpolant === null ) {\r\n\r\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\r\n\t\t\t\tthis._weightInterpolant = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = interpolant.parameterPositions,\r\n\t\t\t\tvalues = interpolant.sampleValues;\r\n\r\n\t\t\ttimes[ 0 ] = now;\r\n\t\t\tvalues[ 0 ] = weightNow;\r\n\t\t\ttimes[ 1 ] = now + duration;\r\n\t\t\tvalues[ 1 ] = weightThen;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Player for AnimationClips.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction AnimationMixer( root ) {\r\n\r\n\t\tthis._root = root;\r\n\t\tthis._initMemoryManager();\r\n\t\tthis._accuIndex = 0;\r\n\r\n\t\tthis.time = 0;\r\n\r\n\t\tthis.timeScale = 1.0;\r\n\r\n\t}\r\n\r\n\tAnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: AnimationMixer,\r\n\r\n\t\t_bindAction: function ( action, prototypeAction ) {\r\n\r\n\t\t\tvar root = action._localRoot || this._root,\r\n\t\t\t\ttracks = action._clip.tracks,\r\n\t\t\t\tnTracks = tracks.length,\r\n\t\t\t\tbindings = action._propertyBindings,\r\n\t\t\t\tinterpolants = action._interpolants,\r\n\t\t\t\trootUuid = root.uuid,\r\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingsByName = bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( bindingsByName === undefined ) {\r\n\r\n\t\t\t\tbindingsByName = {};\r\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingsByName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\r\n\r\n\t\t\t\tvar track = tracks[ i ],\r\n\t\t\t\t\ttrackName = track.name,\r\n\t\t\t\t\tbinding = bindingsByName[ trackName ];\r\n\r\n\t\t\t\tif ( binding !== undefined ) {\r\n\r\n\t\t\t\t\tbindings[ i ] = binding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tbinding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( binding !== undefined ) {\r\n\r\n\t\t\t\t\t\t// existing binding, make sure the cache knows\r\n\r\n\t\t\t\t\t\tif ( binding._cacheIndex === null ) {\r\n\r\n\t\t\t\t\t\t\t++ binding.referenceCount;\r\n\t\t\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar path = prototypeAction && prototypeAction.\r\n\t\t\t\t\t\t_propertyBindings[ i ].binding.parsedPath;\r\n\r\n\t\t\t\t\tbinding = new PropertyMixer(\r\n\t\t\t\t\t\tPropertyBinding.create( root, trackName, path ),\r\n\t\t\t\t\t\ttrack.ValueTypeName, track.getValueSize() );\r\n\r\n\t\t\t\t\t++ binding.referenceCount;\r\n\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\r\n\r\n\t\t\t\t\tbindings[ i ] = binding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tinterpolants[ i ].resultBuffer = binding.buffer;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_activateAction: function ( action ) {\r\n\r\n\t\t\tif ( ! this._isActiveAction( action ) ) {\r\n\r\n\t\t\t\tif ( action._cacheIndex === null ) {\r\n\r\n\t\t\t\t\t// this action has been forgotten by the cache, but the user\r\n\t\t\t\t\t// appears to be still using it -> rebind\r\n\r\n\t\t\t\t\tvar rootUuid = ( action._localRoot || this._root ).uuid,\r\n\t\t\t\t\t\tclipUuid = action._clip.uuid,\r\n\t\t\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\r\n\r\n\t\t\t\t\tthis._bindAction( action,\r\n\t\t\t\t\t\tactionsForClip && actionsForClip.knownActions[ 0 ] );\r\n\r\n\t\t\t\t\tthis._addInactiveAction( action, clipUuid, rootUuid );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar bindings = action._propertyBindings;\r\n\r\n\t\t\t\t// increment reference counts / sort out state\r\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( binding.useCount ++ === 0 ) {\r\n\r\n\t\t\t\t\t\tthis._lendBinding( binding );\r\n\t\t\t\t\t\tbinding.saveOriginalState();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._lendAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_deactivateAction: function ( action ) {\r\n\r\n\t\t\tif ( this._isActiveAction( action ) ) {\r\n\r\n\t\t\t\tvar bindings = action._propertyBindings;\r\n\r\n\t\t\t\t// decrement reference counts / sort out state\r\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( -- binding.useCount === 0 ) {\r\n\r\n\t\t\t\t\t\tbinding.restoreOriginalState();\r\n\t\t\t\t\t\tthis._takeBackBinding( binding );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._takeBackAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// Memory manager\r\n\r\n\t\t_initMemoryManager: function () {\r\n\r\n\t\t\tthis._actions = []; // 'nActiveActions' followed by inactive ones\r\n\t\t\tthis._nActiveActions = 0;\r\n\r\n\t\t\tthis._actionsByClip = {};\r\n\t\t\t// inside:\r\n\t\t\t// {\r\n\t\t\t// \tknownActions: Array< AnimationAction > - used as prototypes\r\n\t\t\t// \tactionByRoot: AnimationAction - lookup\r\n\t\t\t// }\r\n\r\n\r\n\t\t\tthis._bindings = []; // 'nActiveBindings' followed by inactive ones\r\n\t\t\tthis._nActiveBindings = 0;\r\n\r\n\t\t\tthis._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >\r\n\r\n\r\n\t\t\tthis._controlInterpolants = []; // same game as above\r\n\t\t\tthis._nActiveControlInterpolants = 0;\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tthis.stats = {\r\n\r\n\t\t\t\tactions: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._actions.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveActions;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tbindings: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._bindings.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveBindings;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tcontrolInterpolants: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._controlInterpolants.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveControlInterpolants;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\t// Memory management for AnimationAction objects\r\n\r\n\t\t_isActiveAction: function ( action ) {\r\n\r\n\t\t\tvar index = action._cacheIndex;\r\n\t\t\treturn index !== null && index < this._nActiveActions;\r\n\r\n\t\t},\r\n\r\n\t\t_addInactiveAction: function ( action, clipUuid, rootUuid ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip === undefined ) {\r\n\r\n\t\t\t\tactionsForClip = {\r\n\r\n\t\t\t\t\tknownActions: [ action ],\r\n\t\t\t\t\tactionByRoot: {}\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\taction._byClipCacheIndex = 0;\r\n\r\n\t\t\t\tactionsByClip[ clipUuid ] = actionsForClip;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar knownActions = actionsForClip.knownActions;\r\n\r\n\t\t\t\taction._byClipCacheIndex = knownActions.length;\r\n\t\t\t\tknownActions.push( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t\taction._cacheIndex = actions.length;\r\n\t\t\tactions.push( action );\r\n\r\n\t\t\tactionsForClip.actionByRoot[ rootUuid ] = action;\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveAction: function ( action ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ],\r\n\t\t\t\tcacheIndex = action._cacheIndex;\r\n\r\n\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\r\n\t\t\tactions[ cacheIndex ] = lastInactiveAction;\r\n\t\t\tactions.pop();\r\n\r\n\t\t\taction._cacheIndex = null;\r\n\r\n\r\n\t\t\tvar clipUuid = action._clip.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ],\r\n\t\t\t\tknownActionsForClip = actionsForClip.knownActions,\r\n\r\n\t\t\t\tlastKnownAction =\r\n\t\t\t\t\tknownActionsForClip[ knownActionsForClip.length - 1 ],\r\n\r\n\t\t\t\tbyClipCacheIndex = action._byClipCacheIndex;\r\n\r\n\t\t\tlastKnownAction._byClipCacheIndex = byClipCacheIndex;\r\n\t\t\tknownActionsForClip[ byClipCacheIndex ] = lastKnownAction;\r\n\t\t\tknownActionsForClip.pop();\r\n\r\n\t\t\taction._byClipCacheIndex = null;\r\n\r\n\r\n\t\t\tvar actionByRoot = actionsForClip.actionByRoot,\r\n\t\t\t\trootUuid = ( action._localRoot || this._root ).uuid;\r\n\r\n\t\t\tdelete actionByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( knownActionsForClip.length === 0 ) {\r\n\r\n\t\t\t\tdelete actionsByClip[ clipUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._removeInactiveBindingsForAction( action );\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveBindingsForAction: function ( action ) {\r\n\r\n\t\t\tvar bindings = action._propertyBindings;\r\n\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\tif ( -- binding.referenceCount === 0 ) {\r\n\r\n\t\t\t\t\tthis._removeInactiveBinding( binding );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_lendAction: function ( action ) {\r\n\r\n\t\t\t// [ active actions | inactive actions ]\r\n\t\t\t// [ active actions >| inactive actions ]\r\n\t\t\t// s a\r\n\t\t\t// <-swap->\r\n\t\t\t// a s\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tprevIndex = action._cacheIndex,\r\n\r\n\t\t\t\tlastActiveIndex = this._nActiveActions ++,\r\n\r\n\t\t\t\tfirstInactiveAction = actions[ lastActiveIndex ];\r\n\r\n\t\t\taction._cacheIndex = lastActiveIndex;\r\n\t\t\tactions[ lastActiveIndex ] = action;\r\n\r\n\t\t\tfirstInactiveAction._cacheIndex = prevIndex;\r\n\t\t\tactions[ prevIndex ] = firstInactiveAction;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackAction: function ( action ) {\r\n\r\n\t\t\t// [ active actions | inactive actions ]\r\n\t\t\t// [ active actions |< inactive actions ]\r\n\t\t\t// a s\r\n\t\t\t// <-swap->\r\n\t\t\t// s a\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tprevIndex = action._cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveActions,\r\n\r\n\t\t\t\tlastActiveAction = actions[ firstInactiveIndex ];\r\n\r\n\t\t\taction._cacheIndex = firstInactiveIndex;\r\n\t\t\tactions[ firstInactiveIndex ] = action;\r\n\r\n\t\t\tlastActiveAction._cacheIndex = prevIndex;\r\n\t\t\tactions[ prevIndex ] = lastActiveAction;\r\n\r\n\t\t},\r\n\r\n\t\t// Memory management for PropertyMixer objects\r\n\r\n\t\t_addInactiveBinding: function ( binding, rootUuid, trackName ) {\r\n\r\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\r\n\r\n\t\t\t\tbindings = this._bindings;\r\n\r\n\t\t\tif ( bindingByName === undefined ) {\r\n\r\n\t\t\t\tbindingByName = {};\r\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingByName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbindingByName[ trackName ] = binding;\r\n\r\n\t\t\tbinding._cacheIndex = bindings.length;\r\n\t\t\tbindings.push( binding );\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tpropBinding = binding.binding,\r\n\t\t\t\trootUuid = propBinding.rootNode.uuid,\r\n\t\t\t\ttrackName = propBinding.path,\r\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\r\n\r\n\t\t\t\tlastInactiveBinding = bindings[ bindings.length - 1 ],\r\n\t\t\t\tcacheIndex = binding._cacheIndex;\r\n\r\n\t\t\tlastInactiveBinding._cacheIndex = cacheIndex;\r\n\t\t\tbindings[ cacheIndex ] = lastInactiveBinding;\r\n\t\t\tbindings.pop();\r\n\r\n\t\t\tdelete bindingByName[ trackName ];\r\n\r\n\t\t\tif ( Object.keys( bindingByName ).length === 0 ) {\r\n\r\n\t\t\t\tdelete bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_lendBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tprevIndex = binding._cacheIndex,\r\n\r\n\t\t\t\tlastActiveIndex = this._nActiveBindings ++,\r\n\r\n\t\t\t\tfirstInactiveBinding = bindings[ lastActiveIndex ];\r\n\r\n\t\t\tbinding._cacheIndex = lastActiveIndex;\r\n\t\t\tbindings[ lastActiveIndex ] = binding;\r\n\r\n\t\t\tfirstInactiveBinding._cacheIndex = prevIndex;\r\n\t\t\tbindings[ prevIndex ] = firstInactiveBinding;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tprevIndex = binding._cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveBindings,\r\n\r\n\t\t\t\tlastActiveBinding = bindings[ firstInactiveIndex ];\r\n\r\n\t\t\tbinding._cacheIndex = firstInactiveIndex;\r\n\t\t\tbindings[ firstInactiveIndex ] = binding;\r\n\r\n\t\t\tlastActiveBinding._cacheIndex = prevIndex;\r\n\t\t\tbindings[ prevIndex ] = lastActiveBinding;\r\n\r\n\t\t},\r\n\r\n\r\n\t\t// Memory management of Interpolants for weight and time scale\r\n\r\n\t\t_lendControlInterpolant: function () {\r\n\r\n\t\t\tvar interpolants = this._controlInterpolants,\r\n\t\t\t\tlastActiveIndex = this._nActiveControlInterpolants ++,\r\n\t\t\t\tinterpolant = interpolants[ lastActiveIndex ];\r\n\r\n\t\t\tif ( interpolant === undefined ) {\r\n\r\n\t\t\t\tinterpolant = new LinearInterpolant(\r\n\t\t\t\t\tnew Float32Array( 2 ), new Float32Array( 2 ),\r\n\t\t\t\t\t1, this._controlInterpolantsResultBuffer );\r\n\r\n\t\t\t\tinterpolant.__cacheIndex = lastActiveIndex;\r\n\t\t\t\tinterpolants[ lastActiveIndex ] = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn interpolant;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackControlInterpolant: function ( interpolant ) {\r\n\r\n\t\t\tvar interpolants = this._controlInterpolants,\r\n\t\t\t\tprevIndex = interpolant.__cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveControlInterpolants,\r\n\r\n\t\t\t\tlastActiveInterpolant = interpolants[ firstInactiveIndex ];\r\n\r\n\t\t\tinterpolant.__cacheIndex = firstInactiveIndex;\r\n\t\t\tinterpolants[ firstInactiveIndex ] = interpolant;\r\n\r\n\t\t\tlastActiveInterpolant.__cacheIndex = prevIndex;\r\n\t\t\tinterpolants[ prevIndex ] = lastActiveInterpolant;\r\n\r\n\t\t},\r\n\r\n\t\t_controlInterpolantsResultBuffer: new Float32Array( 1 ),\r\n\r\n\t\t// return an action for a clip optionally using a custom root target\r\n\t\t// object (this method allocates a lot of dynamic memory in case a\r\n\t\t// previously unknown clip/root combination is specified)\r\n\t\tclipAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar root = optionalRoot || this._root,\r\n\t\t\t\trootUuid = root.uuid,\r\n\r\n\t\t\t\tclipObject = typeof clip === 'string' ?\r\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\r\n\r\n\t\t\t\tclipUuid = clipObject !== null ? clipObject.uuid : clip,\r\n\r\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ],\r\n\t\t\t\tprototypeAction = null;\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\tvar existingAction =\r\n\t\t\t\t\t\tactionsForClip.actionByRoot[ rootUuid ];\r\n\r\n\t\t\t\tif ( existingAction !== undefined ) {\r\n\r\n\t\t\t\t\treturn existingAction;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// we know the clip, so we don't have to parse all\r\n\t\t\t\t// the bindings again but can just copy\r\n\t\t\t\tprototypeAction = actionsForClip.knownActions[ 0 ];\r\n\r\n\t\t\t\t// also, take the clip from the prototype action\r\n\t\t\t\tif ( clipObject === null )\r\n\t\t\t\t\t{ clipObject = prototypeAction._clip; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// clip must be known when specified via string\r\n\t\t\tif ( clipObject === null ) { return null; }\r\n\r\n\t\t\t// allocate all resources required to run it\r\n\t\t\tvar newAction = new AnimationAction( this, clipObject, optionalRoot );\r\n\r\n\t\t\tthis._bindAction( newAction, prototypeAction );\r\n\r\n\t\t\t// and make the action known to the memory manager\r\n\t\t\tthis._addInactiveAction( newAction, clipUuid, rootUuid );\r\n\r\n\t\t\treturn newAction;\r\n\r\n\t\t},\r\n\r\n\t\t// get an existing action\r\n\t\texistingAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar root = optionalRoot || this._root,\r\n\t\t\t\trootUuid = root.uuid,\r\n\r\n\t\t\t\tclipObject = typeof clip === 'string' ?\r\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\r\n\r\n\t\t\t\tclipUuid = clipObject ? clipObject.uuid : clip,\r\n\r\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\treturn actionsForClip.actionByRoot[ rootUuid ] || null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\t// deactivates all previously scheduled actions\r\n\t\tstopAllAction: function () {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tnActions = this._nActiveActions,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = this._nActiveBindings;\r\n\r\n\t\t\tthis._nActiveActions = 0;\r\n\t\t\tthis._nActiveBindings = 0;\r\n\r\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\r\n\r\n\t\t\t\tactions[ i ].reset();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].useCount = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// advance the time and update apply the animation\r\n\t\tupdate: function ( deltaTime ) {\r\n\r\n\t\t\tdeltaTime *= this.timeScale;\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tnActions = this._nActiveActions,\r\n\r\n\t\t\t\ttime = this.time += deltaTime,\r\n\t\t\t\ttimeDirection = Math.sign( deltaTime ),\r\n\r\n\t\t\t\taccuIndex = this._accuIndex ^= 1;\r\n\r\n\t\t\t// run active actions\r\n\r\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\r\n\r\n\t\t\t\tvar action = actions[ i ];\r\n\r\n\t\t\t\taction._update( time, deltaTime, timeDirection, accuIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update scene graph\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tnBindings = this._nActiveBindings;\r\n\r\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].apply( accuIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Allows you to seek to a specific time in an animation.\r\n\t\tsetTime: function ( timeInSeconds ) {\r\n\r\n\t\t\tthis.time = 0; // Zero out time attribute for AnimationMixer object;\r\n\t\t\tfor ( var i = 0; i < this._actions.length; i ++ ) {\r\n\r\n\t\t\t\tthis._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.update( timeInSeconds ); // Update used to set exact time. Returns \"this\" AnimationMixer object.\r\n\r\n\t\t},\r\n\r\n\t\t// return this mixer's root target object\r\n\t\tgetRoot: function () {\r\n\r\n\t\t\treturn this._root;\r\n\r\n\t\t},\r\n\r\n\t\t// free all resources specific to a particular clip\r\n\t\tuncacheClip: function ( clip ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tclipUuid = clip.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\t// note: just calling _removeInactiveAction would mess up the\r\n\t\t\t\t// iteration state and also require updating the state we can\r\n\t\t\t\t// just throw away\r\n\r\n\t\t\t\tvar actionsToRemove = actionsForClip.knownActions;\r\n\r\n\t\t\t\tfor ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar action = actionsToRemove[ i ];\r\n\r\n\t\t\t\t\tthis._deactivateAction( action );\r\n\r\n\t\t\t\t\tvar cacheIndex = action._cacheIndex,\r\n\t\t\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ];\r\n\r\n\t\t\t\t\taction._cacheIndex = null;\r\n\t\t\t\t\taction._byClipCacheIndex = null;\r\n\r\n\t\t\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\r\n\t\t\t\t\tactions[ cacheIndex ] = lastInactiveAction;\r\n\t\t\t\t\tactions.pop();\r\n\r\n\t\t\t\t\tthis._removeInactiveBindingsForAction( action );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdelete actionsByClip[ clipUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// free all resources specific to a particular root target object\r\n\t\tuncacheRoot: function ( root ) {\r\n\r\n\t\t\tvar rootUuid = root.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip;\r\n\r\n\t\t\tfor ( var clipUuid in actionsByClip ) {\r\n\r\n\t\t\t\tvar actionByRoot = actionsByClip[ clipUuid ].actionByRoot,\r\n\t\t\t\t\taction = actionByRoot[ rootUuid ];\r\n\r\n\t\t\t\tif ( action !== undefined ) {\r\n\r\n\t\t\t\t\tthis._deactivateAction( action );\r\n\t\t\t\t\tthis._removeInactiveAction( action );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( bindingByName !== undefined ) {\r\n\r\n\t\t\t\tfor ( var trackName in bindingByName ) {\r\n\r\n\t\t\t\t\tvar binding = bindingByName[ trackName ];\r\n\t\t\t\t\tbinding.restoreOriginalState();\r\n\t\t\t\t\tthis._removeInactiveBinding( binding );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// remove a targeted clip from the cache\r\n\t\tuncacheAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar action = this.existingAction( clip, optionalRoot );\r\n\r\n\t\t\tif ( action !== null ) {\r\n\r\n\t\t\t\tthis._deactivateAction( action );\r\n\t\t\t\tthis._removeInactiveAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Uniform( value ) {\r\n\r\n\t\tif ( typeof value === 'string' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Uniform: Type parameter is no longer needed.' );\r\n\t\t\tvalue = arguments[ 1 ];\r\n\r\n\t\t}\r\n\r\n\t\tthis.value = value;\r\n\r\n\t}\r\n\r\n\tUniform.prototype.clone = function () {\r\n\r\n\t\treturn new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );\r\n\r\n\t};\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {\r\n\r\n\t\tInterleavedBuffer.call( this, array, stride );\r\n\r\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\r\n\r\n\t}\r\n\r\n\tInstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {\r\n\r\n\t\tconstructor: InstancedInterleavedBuffer,\r\n\r\n\t\tisInstancedInterleavedBuffer: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tInterleavedBuffer.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author bhouston / http://clara.io/\r\n\t * @author stephomi / http://stephaneginier.com/\r\n\t */\r\n\r\n\tfunction Raycaster( origin, direction, near, far ) {\r\n\r\n\t\tthis.ray = new Ray( origin, direction );\r\n\t\t// direction is assumed to be normalized (for accurate distance calculations)\r\n\r\n\t\tthis.near = near || 0;\r\n\t\tthis.far = far || Infinity;\r\n\t\tthis.camera = null;\r\n\r\n\t\tthis.params = {\r\n\t\t\tMesh: {},\r\n\t\t\tLine: {},\r\n\t\t\tLOD: {},\r\n\t\t\tPoints: { threshold: 1 },\r\n\t\t\tSprite: {}\r\n\t\t};\r\n\r\n\t\tObject.defineProperties( this.params, {\r\n\t\t\tPointCloud: {\r\n\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );\r\n\t\t\t\t\treturn this.Points;\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\tfunction ascSort( a, b ) {\r\n\r\n\t\treturn a.distance - b.distance;\r\n\r\n\t}\r\n\r\n\tfunction intersectObject( object, raycaster, intersects, recursive ) {\r\n\r\n\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\tobject.raycast( raycaster, intersects );\r\n\r\n\t\tif ( recursive === true ) {\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tintersectObject( children[ i ], raycaster, intersects, true );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Raycaster.prototype, {\r\n\r\n\t\tlinePrecision: 1,\r\n\r\n\t\tset: function ( origin, direction ) {\r\n\r\n\t\t\t// direction is assumed to be normalized (for accurate distance calculations)\r\n\r\n\t\t\tthis.ray.set( origin, direction );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCamera: function ( coords, camera ) {\r\n\r\n\t\t\tif ( ( camera && camera.isPerspectiveCamera ) ) {\r\n\r\n\t\t\t\tthis.ray.origin.setFromMatrixPosition( camera.matrixWorld );\r\n\t\t\t\tthis.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();\r\n\t\t\t\tthis.camera = camera;\r\n\r\n\t\t\t} else if ( ( camera && camera.isOrthographicCamera ) ) {\r\n\r\n\t\t\t\tthis.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera\r\n\t\t\t\tthis.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );\r\n\t\t\t\tthis.camera = camera;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Raycaster: Unsupported camera type.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tintersectObject: function ( object, recursive, optionalTarget ) {\r\n\r\n\t\t\tvar intersects = optionalTarget || [];\r\n\r\n\t\t\tintersectObject( object, this, intersects, recursive );\r\n\r\n\t\t\tintersects.sort( ascSort );\r\n\r\n\t\t\treturn intersects;\r\n\r\n\t\t},\r\n\r\n\t\tintersectObjects: function ( objects, recursive, optionalTarget ) {\r\n\r\n\t\t\tvar intersects = optionalTarget || [];\r\n\r\n\t\t\tif ( Array.isArray( objects ) === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );\r\n\t\t\t\treturn intersects;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, l = objects.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tintersectObject( objects[ i ], this, intersects, recursive );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tintersects.sort( ascSort );\r\n\r\n\t\t\treturn intersects;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system\r\n\t *\r\n\t * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.\r\n\t * The azimuthal angle (theta) is measured from the positive z-axis.\r\n\t */\r\n\r\n\tfunction Spherical( radius, phi, theta ) {\r\n\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0;\r\n\t\tthis.phi = ( phi !== undefined ) ? phi : 0; // polar angle\r\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle\r\n\r\n\t\treturn this;\r\n\r\n\t}\r\n\r\n\tObject.assign( Spherical.prototype, {\r\n\r\n\t\tset: function ( radius, phi, theta ) {\r\n\r\n\t\t\tthis.radius = radius;\r\n\t\t\tthis.phi = phi;\r\n\t\t\tthis.theta = theta;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( other ) {\r\n\r\n\t\t\tthis.radius = other.radius;\r\n\t\t\tthis.phi = other.phi;\r\n\t\t\tthis.theta = other.theta;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// restrict phi to be betwee EPS and PI-EPS\r\n\t\tmakeSafe: function () {\r\n\r\n\t\t\tvar EPS = 0.000001;\r\n\t\t\tthis.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v ) {\r\n\r\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\r\n\r\n\t\t\tthis.radius = Math.sqrt( x * x + y * y + z * z );\r\n\r\n\t\t\tif ( this.radius === 0 ) {\r\n\r\n\t\t\t\tthis.theta = 0;\r\n\t\t\t\tthis.phi = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.theta = Math.atan2( x, z );\r\n\t\t\t\tthis.phi = Math.acos( _Math.clamp( y / this.radius, - 1, 1 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system\r\n\t *\r\n\t */\r\n\r\n\tfunction Cylindrical( radius, theta, y ) {\r\n\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane\r\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis\r\n\t\tthis.y = ( y !== undefined ) ? y : 0; // height above the x-z plane\r\n\r\n\t\treturn this;\r\n\r\n\t}\r\n\r\n\tObject.assign( Cylindrical.prototype, {\r\n\r\n\t\tset: function ( radius, theta, y ) {\r\n\r\n\t\t\tthis.radius = radius;\r\n\t\t\tthis.theta = theta;\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( other ) {\r\n\r\n\t\t\tthis.radius = other.radius;\r\n\t\t\tthis.theta = other.theta;\r\n\t\t\tthis.y = other.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v ) {\r\n\r\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\r\n\r\n\t\t\tthis.radius = Math.sqrt( x * x + z * z );\r\n\t\t\tthis.theta = Math.atan2( x, z );\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _vector$7 = new Vector2();\r\n\r\n\tfunction Box2( min, max ) {\r\n\r\n\t\tthis.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );\r\n\t\tthis.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );\r\n\r\n\t}\r\n\r\n\tObject.assign( Box2.prototype, {\r\n\r\n\t\tset: function ( min, max ) {\r\n\r\n\t\t\tthis.min.copy( min );\r\n\t\t\tthis.max.copy( max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByPoint( points[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCenterAndSize: function ( center, size ) {\r\n\r\n\t\t\tvar halfSize = _vector$7.copy( size ).multiplyScalar( 0.5 );\r\n\t\t\tthis.min.copy( center ).sub( halfSize );\r\n\t\t\tthis.max.copy( center ).add( halfSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( box ) {\r\n\r\n\t\t\tthis.min.copy( box.min );\r\n\t\t\tthis.max.copy( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeEmpty: function () {\r\n\r\n\t\t\tthis.min.x = this.min.y = + Infinity;\r\n\t\t\tthis.max.x = this.max.y = - Infinity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tisEmpty: function () {\r\n\r\n\t\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\r\n\r\n\t\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tgetSize: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getSize() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );\r\n\r\n\t\t},\r\n\r\n\t\texpandByPoint: function ( point ) {\r\n\r\n\t\t\tthis.min.min( point );\r\n\t\t\tthis.max.max( point );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByVector: function ( vector ) {\r\n\r\n\t\t\tthis.min.sub( vector );\r\n\t\t\tthis.max.add( vector );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.min.addScalar( - scalar );\r\n\t\t\tthis.max.addScalar( scalar );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn point.x < this.min.x || point.x > this.max.x ||\r\n\t\t\t\tpoint.y < this.min.y || point.y > this.max.y ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsBox: function ( box ) {\r\n\r\n\t\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\r\n\t\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y;\r\n\r\n\t\t},\r\n\r\n\t\tgetParameter: function ( point, target ) {\r\n\r\n\t\t\t// This can potentially have a divide by zero if the box\r\n\t\t\t// has a size dimension of 0.\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getParameter() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set(\r\n\t\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\r\n\t\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y )\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\t// using 4 splitting planes to rule out intersections\r\n\r\n\t\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\r\n\t\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\tvar clampedPoint = _vector$7.copy( point ).clamp( this.min, this.max );\r\n\t\t\treturn clampedPoint.sub( point ).length();\r\n\r\n\t\t},\r\n\r\n\t\tintersect: function ( box ) {\r\n\r\n\t\t\tthis.min.max( box.min );\r\n\t\t\tthis.max.min( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tunion: function ( box ) {\r\n\r\n\t\t\tthis.min.min( box.min );\r\n\t\t\tthis.max.max( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.min.add( offset );\r\n\t\t\tthis.max.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( box ) {\r\n\r\n\t\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _startP = new Vector3();\r\n\tvar _startEnd = new Vector3();\r\n\r\n\tfunction Line3( start, end ) {\r\n\r\n\t\tthis.start = ( start !== undefined ) ? start : new Vector3();\r\n\t\tthis.end = ( end !== undefined ) ? end : new Vector3();\r\n\r\n\t}\r\n\r\n\tObject.assign( Line3.prototype, {\r\n\r\n\t\tset: function ( start, end ) {\r\n\r\n\t\t\tthis.start.copy( start );\r\n\t\t\tthis.end.copy( end );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( line ) {\r\n\r\n\t\t\tthis.start.copy( line.start );\r\n\t\t\tthis.end.copy( line.end );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tdelta: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .delta() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.subVectors( this.end, this.start );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSq: function () {\r\n\r\n\t\t\treturn this.start.distanceToSquared( this.end );\r\n\r\n\t\t},\r\n\r\n\t\tdistance: function () {\r\n\r\n\t\t\treturn this.start.distanceTo( this.end );\r\n\r\n\t\t},\r\n\r\n\t\tat: function ( t, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .at() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPointParameter: function ( point, clampToLine ) {\r\n\r\n\t\t\t_startP.subVectors( point, this.start );\r\n\t\t\t_startEnd.subVectors( this.end, this.start );\r\n\r\n\t\t\tvar startEnd2 = _startEnd.dot( _startEnd );\r\n\t\t\tvar startEnd_startP = _startEnd.dot( _startP );\r\n\r\n\t\t\tvar t = startEnd_startP / startEnd2;\r\n\r\n\t\t\tif ( clampToLine ) {\r\n\r\n\t\t\t\tt = _Math.clamp( t, 0, 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn t;\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( point, clampToLine, target ) {\r\n\r\n\t\t\tvar t = this.closestPointToPointParameter( point, clampToLine );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\tthis.start.applyMatrix4( matrix );\r\n\t\t\tthis.end.applyMatrix4( matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( line ) {\r\n\r\n\t\t\treturn line.start.equals( this.start ) && line.end.equals( this.end );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction ImmediateRenderObject( material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.material = material;\r\n\t\tthis.render = function ( /* renderCallback */ ) {};\r\n\r\n\t}\r\n\r\n\tImmediateRenderObject.prototype = Object.create( Object3D.prototype );\r\n\tImmediateRenderObject.prototype.constructor = ImmediateRenderObject;\r\n\r\n\tImmediateRenderObject.prototype.isImmediateRenderObject = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$5 = new Vector3();\r\n\tvar _v2$3 = new Vector3();\r\n\tvar _normalMatrix$1 = new Matrix3();\r\n\tvar _keys = [ 'a', 'b', 'c' ];\r\n\r\n\tfunction VertexNormalsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xff0000;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar nNormals = 0;\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.faces.length * 3;\r\n\r\n\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.attributes.normal.count;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tVertexNormalsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tVertexNormalsHelper.prototype.constructor = VertexNormalsHelper;\r\n\r\n\tVertexNormalsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\t_normalMatrix$1.getNormalMatrix( this.object.matrixWorld );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tvar vertices = objGeometry.vertices;\r\n\r\n\t\t\tvar faces = objGeometry.faces;\r\n\r\n\t\t\tvar idx = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar vertex = vertices[ face[ _keys[ j ] ] ];\r\n\r\n\t\t\t\t\tvar normal = face.vertexNormals[ j ];\r\n\r\n\t\t\t\t\t_v1$5.copy( vertex ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t\t\t_v2$3.copy( normal ).applyMatrix3( _normalMatrix$1 ).normalize().multiplyScalar( this.size ).add( _v1$5 );\r\n\r\n\t\t\t\t\tposition.setXYZ( idx, _v1$5.x, _v1$5.y, _v1$5.z );\r\n\r\n\t\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\t\tposition.setXYZ( idx, _v2$3.x, _v2$3.y, _v2$3.z );\r\n\r\n\t\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\r\n\r\n\t\t\tvar objPos = objGeometry.attributes.position;\r\n\r\n\t\t\tvar objNorm = objGeometry.attributes.normal;\r\n\r\n\t\t\tvar idx = 0;\r\n\r\n\t\t\t// for simplicity, ignore index and drawcalls, and render every normal\r\n\r\n\t\t\tfor ( var j = 0, jl = objPos.count; j < jl; j ++ ) {\r\n\r\n\t\t\t\t_v1$5.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t\t_v2$3.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );\r\n\r\n\t\t\t\t_v2$3.applyMatrix3( _normalMatrix$1 ).normalize().multiplyScalar( this.size ).add( _v1$5 );\r\n\r\n\t\t\t\tposition.setXYZ( idx, _v1$5.x, _v1$5.y, _v1$5.z );\r\n\r\n\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\tposition.setXYZ( idx, _v2$3.x, _v2$3.y, _v2$3.z );\r\n\r\n\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$6 = new Vector3();\r\n\tvar _v2$4 = new Vector3();\r\n\r\n\tfunction VertexTangentsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0x00ffff;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( ! ( objGeometry && objGeometry.isBufferGeometry ) ) {\r\n\r\n\t\t\tconsole.error( 'THREE.VertexTangentsHelper: geometry not an instance of THREE.BufferGeometry.', objGeometry );\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tvar nTangents = objGeometry.attributes.tangent.count;\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nTangents * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tVertexTangentsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tVertexTangentsHelper.prototype.constructor = VertexTangentsHelper;\r\n\r\n\tVertexTangentsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tvar objPos = objGeometry.attributes.position;\r\n\r\n\t\tvar objTan = objGeometry.attributes.tangent;\r\n\r\n\t\tvar idx = 0;\r\n\r\n\t\t// for simplicity, ignore index and drawcalls, and render every tangent\r\n\r\n\t\tfor ( var j = 0, jl = objPos.count; j < jl; j ++ ) {\r\n\r\n\t\t\t_v1$6.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t_v2$4.set( objTan.getX( j ), objTan.getY( j ), objTan.getZ( j ) );\r\n\r\n\t\t\t_v2$4.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( _v1$6 );\r\n\r\n\t\t\tposition.setXYZ( idx, _v1$6.x, _v1$6.y, _v1$6.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t\tposition.setXYZ( idx, _v2$4.x, _v2$4.y, _v2$4.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _vector$8 = new Vector3();\r\n\r\n\tfunction SpotLightHelper( light, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = [\r\n\t\t\t0, 0, 0, \t0, 0, 1,\r\n\t\t\t0, 0, 0, \t1, 0, 1,\r\n\t\t\t0, 0, 0,\t- 1, 0, 1,\r\n\t\t\t0, 0, 0, \t0, 1, 1,\r\n\t\t\t0, 0, 0, \t0, - 1, 1\r\n\t\t];\r\n\r\n\t\tfor ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {\r\n\r\n\t\t\tvar p1 = ( i / l ) * Math.PI * 2;\r\n\t\t\tvar p2 = ( j / l ) * Math.PI * 2;\r\n\r\n\t\t\tpositions.push(\r\n\t\t\t\tMath.cos( p1 ), Math.sin( p1 ), 1,\r\n\t\t\t\tMath.cos( p2 ), Math.sin( p2 ), 1\r\n\t\t\t);\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tthis.cone = new LineSegments( geometry, material );\r\n\t\tthis.add( this.cone );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tSpotLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tSpotLightHelper.prototype.constructor = SpotLightHelper;\r\n\r\n\tSpotLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.cone.geometry.dispose();\r\n\t\tthis.cone.material.dispose();\r\n\r\n\t};\r\n\r\n\tSpotLightHelper.prototype.update = function () {\r\n\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tvar coneLength = this.light.distance ? this.light.distance : 1000;\r\n\t\tvar coneWidth = coneLength * Math.tan( this.light.angle );\r\n\r\n\t\tthis.cone.scale.set( coneWidth, coneWidth, coneLength );\r\n\r\n\t\t_vector$8.setFromMatrixPosition( this.light.target.matrixWorld );\r\n\r\n\t\tthis.cone.lookAt( _vector$8 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.cone.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.cone.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author Sean Griffin / http://twitter.com/sgrif\r\n\t * @author Michael Guerrero / http://realitymeltdown.com\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author ikerr / http://verold.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _vector$9 = new Vector3();\r\n\tvar _boneMatrix = new Matrix4();\r\n\tvar _matrixWorldInv = new Matrix4();\r\n\r\n\tfunction getBoneList( object ) {\r\n\r\n\t\tvar boneList = [];\r\n\r\n\t\tif ( object && object.isBone ) {\r\n\r\n\t\t\tboneList.push( object );\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i < object.children.length; i ++ ) {\r\n\r\n\t\t\tboneList.push.apply( boneList, getBoneList( object.children[ i ] ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn boneList;\r\n\r\n\t}\r\n\r\n\tfunction SkeletonHelper( object ) {\r\n\r\n\t\tvar bones = getBoneList( object );\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar color1 = new Color( 0, 0, 1 );\r\n\t\tvar color2 = new Color( 0, 1, 0 );\r\n\r\n\t\tfor ( var i = 0; i < bones.length; i ++ ) {\r\n\r\n\t\t\tvar bone = bones[ i ];\r\n\r\n\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\t\tcolors.push( color1.r, color1.g, color1.b );\r\n\t\t\t\tcolors.push( color2.r, color2.g, color2.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t\tthis.root = object;\r\n\t\tthis.bones = bones;\r\n\r\n\t\tthis.matrix = object.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t}\r\n\r\n\tSkeletonHelper.prototype = Object.create( LineSegments.prototype );\r\n\tSkeletonHelper.prototype.constructor = SkeletonHelper;\r\n\r\n\tSkeletonHelper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar bones = this.bones;\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar position = geometry.getAttribute( 'position' );\r\n\r\n\t\t_matrixWorldInv.getInverse( this.root.matrixWorld );\r\n\r\n\t\tfor ( var i = 0, j = 0; i < bones.length; i ++ ) {\r\n\r\n\t\t\tvar bone = bones[ i ];\r\n\r\n\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\t_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );\r\n\t\t\t\t_vector$9.setFromMatrixPosition( _boneMatrix );\r\n\t\t\t\tposition.setXYZ( j, _vector$9.x, _vector$9.y, _vector$9.z );\r\n\r\n\t\t\t\t_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );\r\n\t\t\t\t_vector$9.setFromMatrixPosition( _boneMatrix );\r\n\t\t\t\tposition.setXYZ( j + 1, _vector$9.x, _vector$9.y, _vector$9.z );\r\n\r\n\t\t\t\tj += 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction PointLightHelper( light, sphereSize, color ) {\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new SphereBufferGeometry( sphereSize, 4, 2 );\r\n\t\tvar material = new MeshBasicMaterial( { wireframe: true, fog: false } );\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.matrix = this.light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\r\n\t\t/*\r\n\t\tvar distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );\r\n\t\tvar distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );\r\n\r\n\t\tthis.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );\r\n\t\tthis.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );\r\n\r\n\t\tvar d = light.distance;\r\n\r\n\t\tif ( d === 0.0 ) {\r\n\r\n\t\t\tthis.lightDistance.visible = false;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightDistance.scale.set( d, d, d );\r\n\r\n\t\t}\r\n\r\n\t\tthis.add( this.lightDistance );\r\n\t\t*/\r\n\r\n\t}\r\n\r\n\tPointLightHelper.prototype = Object.create( Mesh.prototype );\r\n\tPointLightHelper.prototype.constructor = PointLightHelper;\r\n\r\n\tPointLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\r\n\t};\r\n\r\n\tPointLightHelper.prototype.update = function () {\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\tvar d = this.light.distance;\r\n\r\n\t\tif ( d === 0.0 ) {\r\n\r\n\t\t\tthis.lightDistance.visible = false;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightDistance.visible = true;\r\n\t\t\tthis.lightDistance.scale.set( d, d, d );\r\n\r\n\t\t}\r\n\t\t*/\r\n\r\n\t};\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * This helper must be added as a child of the light\r\n\t */\r\n\r\n\tfunction RectAreaLightHelper( light, color ) {\r\n\r\n\t\tthis.type = 'RectAreaLightHelper';\r\n\r\n\t\tthis.light = light;\r\n\r\n\t\tthis.color = color; // optional hardwired color for the helper\r\n\r\n\t\tvar positions = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\t\tgeometry.computeBoundingSphere();\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\t//\r\n\r\n\t\tvar positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];\r\n\r\n\t\tvar geometry2 = new BufferGeometry();\r\n\t\tgeometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\r\n\t\tgeometry2.computeBoundingSphere();\r\n\r\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { side: BackSide, fog: false } ) ) );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tRectAreaLightHelper.prototype = Object.create( Line.prototype );\r\n\tRectAreaLightHelper.prototype.constructor = RectAreaLightHelper;\r\n\r\n\tRectAreaLightHelper.prototype.update = function () {\r\n\r\n\t\tthis.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\t\t\tthis.children[ 0 ].material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );\r\n\r\n\t\t\t// prevent hue shift\r\n\t\t\tvar c = this.material.color;\r\n\t\t\tvar max = Math.max( c.r, c.g, c.b );\r\n\t\t\tif ( max > 1 ) { c.multiplyScalar( 1 / max ); }\r\n\r\n\t\t\tthis.children[ 0 ].material.color.copy( this.material.color );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tRectAreaLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\t\tthis.children[ 0 ].geometry.dispose();\r\n\t\tthis.children[ 0 ].material.dispose();\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _vector$a = new Vector3();\r\n\tvar _color1 = new Color();\r\n\tvar _color2 = new Color();\r\n\r\n\tfunction HemisphereLightHelper( light, size, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new OctahedronBufferGeometry( size );\r\n\t\tgeometry.rotateY( Math.PI * 0.5 );\r\n\r\n\t\tthis.material = new MeshBasicMaterial( { wireframe: true, fog: false } );\r\n\t\tif ( this.color === undefined ) { this.material.vertexColors = VertexColors; }\r\n\r\n\t\tvar position = geometry.getAttribute( 'position' );\r\n\t\tvar colors = new Float32Array( position.count * 3 );\r\n\r\n\t\tgeometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );\r\n\r\n\t\tthis.add( new Mesh( geometry, this.material ) );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tHemisphereLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tHemisphereLightHelper.prototype.constructor = HemisphereLightHelper;\r\n\r\n\tHemisphereLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.children[ 0 ].geometry.dispose();\r\n\t\tthis.children[ 0 ].material.dispose();\r\n\r\n\t};\r\n\r\n\tHemisphereLightHelper.prototype.update = function () {\r\n\r\n\t\tvar mesh = this.children[ 0 ];\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tvar colors = mesh.geometry.getAttribute( 'color' );\r\n\r\n\t\t\t_color1.copy( this.light.color );\r\n\t\t\t_color2.copy( this.light.groundColor );\r\n\r\n\t\t\tfor ( var i = 0, l = colors.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar color = ( i < ( l / 2 ) ) ? _color1 : _color2;\r\n\r\n\t\t\t\tcolors.setXYZ( i, color.r, color.g, color.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcolors.needsUpdate = true;\r\n\r\n\t\t}\r\n\r\n\t\tmesh.lookAt( _vector$a.setFromMatrixPosition( this.light.matrixWorld ).negate() );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction LightProbeHelper( lightProbe, size ) {\r\n\r\n\t\tthis.lightProbe = lightProbe;\r\n\r\n\t\tthis.size = size;\r\n\r\n\t\tvar defines = {};\r\n\t\tdefines[ 'GAMMA_OUTPUT' ] = \"\";\r\n\r\n\t\t// material\r\n\t\tvar material = new ShaderMaterial( {\r\n\r\n\t\t\tdefines: defines,\r\n\r\n\t\t\tuniforms: {\r\n\r\n\t\t\t\tsh: { value: this.lightProbe.sh.coefficients }, // by reference\r\n\r\n\t\t\t\tintensity: { value: this.lightProbe.intensity }\r\n\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: [\r\n\r\n\t\t\t\t'varying vec3 vNormal;',\r\n\r\n\t\t\t\t'void main() {',\r\n\r\n\t\t\t\t'\tvNormal = normalize( normalMatrix * normal );',\r\n\r\n\t\t\t\t'\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',\r\n\r\n\t\t\t\t'}' ].join( '\\n' ),\r\n\r\n\t\t\tfragmentShader: [\r\n\r\n\t\t\t\t'#define RECIPROCAL_PI 0.318309886',\r\n\r\n\t\t\t\t'vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {',\r\n\r\n\t\t\t\t'\t// matrix is assumed to be orthogonal',\r\n\r\n\t\t\t\t'\treturn normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'vec3 linearToOutput( in vec3 a ) {',\r\n\r\n\t\t\t\t'\t#ifdef GAMMA_OUTPUT',\r\n\r\n\t\t\t\t'\t\treturn pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );',\r\n\r\n\t\t\t\t'\t#else',\r\n\r\n\t\t\t\t'\t\treturn a;',\r\n\r\n\t\t\t\t'\t#endif',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf',\r\n\t\t\t\t'vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {',\r\n\r\n\t\t\t\t'\t// normal is assumed to have unit length',\r\n\r\n\t\t\t\t'\tfloat x = normal.x, y = normal.y, z = normal.z;',\r\n\r\n\t\t\t\t'\t// band 0',\r\n\t\t\t\t'\tvec3 result = shCoefficients[ 0 ] * 0.886227;',\r\n\r\n\t\t\t\t'\t// band 1',\r\n\t\t\t\t'\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;',\r\n\t\t\t\t'\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;',\r\n\r\n\t\t\t\t'\t// band 2',\r\n\t\t\t\t'\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;',\r\n\t\t\t\t'\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );',\r\n\t\t\t\t'\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );',\r\n\r\n\t\t\t\t'\treturn result;',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'uniform vec3 sh[ 9 ]; // sh coefficients',\r\n\r\n\t\t\t\t'uniform float intensity; // light probe intensity',\r\n\r\n\t\t\t\t'varying vec3 vNormal;',\r\n\r\n\t\t\t\t'void main() {',\r\n\r\n\t\t\t\t'\tvec3 normal = normalize( vNormal );',\r\n\r\n\t\t\t\t'\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );',\r\n\r\n\t\t\t\t'\tvec3 irradiance = shGetIrradianceAt( worldNormal, sh );',\r\n\r\n\t\t\t\t'\tvec3 outgoingLight = RECIPROCAL_PI * irradiance * intensity;',\r\n\r\n\t\t\t\t'\toutgoingLight = linearToOutput( outgoingLight );',\r\n\r\n\t\t\t\t'\tgl_FragColor = vec4( outgoingLight, 1.0 );',\r\n\r\n\t\t\t\t'}'\r\n\r\n\t\t\t].join( '\\n' )\r\n\r\n\t\t} );\r\n\r\n\t\tvar geometry = new SphereBufferGeometry( 1, 32, 16 );\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.onBeforeRender();\r\n\r\n\t}\r\n\r\n\tLightProbeHelper.prototype = Object.create( Mesh.prototype );\r\n\tLightProbeHelper.prototype.constructor = LightProbeHelper;\r\n\r\n\tLightProbeHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\r\n\t};\r\n\r\n\tLightProbeHelper.prototype.onBeforeRender = function () {\r\n\r\n\t\tthis.position.copy( this.lightProbe.position );\r\n\r\n\t\tthis.scale.set( 1, 1, 1 ).multiplyScalar( this.size );\r\n\r\n\t\tthis.material.uniforms.intensity.value = this.lightProbe.intensity;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction GridHelper( size, divisions, color1, color2 ) {\r\n\r\n\t\tsize = size || 10;\r\n\t\tdivisions = divisions || 10;\r\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\r\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\r\n\r\n\t\tvar center = divisions / 2;\r\n\t\tvar step = size / divisions;\r\n\t\tvar halfSize = size / 2;\r\n\r\n\t\tvar vertices = [], colors = [];\r\n\r\n\t\tfor ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {\r\n\r\n\t\t\tvertices.push( - halfSize, 0, k, halfSize, 0, k );\r\n\t\t\tvertices.push( k, 0, - halfSize, k, 0, halfSize );\r\n\r\n\t\t\tvar color = i === center ? color1 : color2;\r\n\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\r\n\t\t}\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tGridHelper.prototype = Object.assign( Object.create( LineSegments.prototype ), {\r\n\r\n\t\tconstructor: GridHelper,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLineSegments.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.geometry.copy( source.geometry );\r\n\t\t\tthis.material.copy( source.material );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t * @author Hectate / http://www.github.com/Hectate\r\n\t */\r\n\r\n\tfunction PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {\r\n\r\n\t\tradius = radius || 10;\r\n\t\tradials = radials || 16;\r\n\t\tcircles = circles || 8;\r\n\t\tdivisions = divisions || 64;\r\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\r\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar x, z;\r\n\t\tvar v, i, j, r, color;\r\n\r\n\t\t// create the radials\r\n\r\n\t\tfor ( i = 0; i <= radials; i ++ ) {\r\n\r\n\t\t\tv = ( i / radials ) * ( Math.PI * 2 );\r\n\r\n\t\t\tx = Math.sin( v ) * radius;\r\n\t\t\tz = Math.cos( v ) * radius;\r\n\r\n\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\tvertices.push( x, 0, z );\r\n\r\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\r\n\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t}\r\n\r\n\t\t// create the circles\r\n\r\n\t\tfor ( i = 0; i <= circles; i ++ ) {\r\n\r\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\r\n\r\n\t\t\tr = radius - ( radius / circles * i );\r\n\r\n\t\t\tfor ( j = 0; j < divisions; j ++ ) {\r\n\r\n\t\t\t\t// first vertex\r\n\r\n\t\t\t\tv = ( j / divisions ) * ( Math.PI * 2 );\r\n\r\n\t\t\t\tx = Math.sin( v ) * r;\r\n\t\t\t\tz = Math.cos( v ) * r;\r\n\r\n\t\t\t\tvertices.push( x, 0, z );\r\n\t\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\t\t// second vertex\r\n\r\n\t\t\t\tv = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );\r\n\r\n\t\t\t\tx = Math.sin( v ) * r;\r\n\t\t\t\tz = Math.cos( v ) * r;\r\n\r\n\t\t\t\tvertices.push( x, 0, z );\r\n\t\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tPolarGridHelper.prototype = Object.create( LineSegments.prototype );\r\n\tPolarGridHelper.prototype.constructor = PolarGridHelper;\n\n\t/**\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {\r\n\r\n\t\tthis.audio = audio;\r\n\t\tthis.range = range || 1;\r\n\t\tthis.divisionsInnerAngle = divisionsInnerAngle || 16;\r\n\t\tthis.divisionsOuterAngle = divisionsOuterAngle || 2;\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tvar divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;\r\n\t\tvar positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );\r\n\t\tgeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );\r\n\r\n\t\tvar materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );\r\n\t\tvar materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );\r\n\r\n\t\tLine.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tPositionalAudioHelper.prototype = Object.create( Line.prototype );\r\n\tPositionalAudioHelper.prototype.constructor = PositionalAudioHelper;\r\n\r\n\tPositionalAudioHelper.prototype.update = function () {\r\n\r\n\t\tvar audio = this.audio;\r\n\t\tvar range = this.range;\r\n\t\tvar divisionsInnerAngle = this.divisionsInnerAngle;\r\n\t\tvar divisionsOuterAngle = this.divisionsOuterAngle;\r\n\r\n\t\tvar coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );\r\n\t\tvar coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );\r\n\r\n\t\tvar halfConeInnerAngle = coneInnerAngle / 2;\r\n\t\tvar halfConeOuterAngle = coneOuterAngle / 2;\r\n\r\n\t\tvar start = 0;\r\n\t\tvar count = 0;\r\n\t\tvar i, stride;\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar positionAttribute = geometry.attributes.position;\r\n\r\n\t\tgeometry.clearGroups();\r\n\r\n\t\t//\r\n\r\n\t\tfunction generateSegment( from, to, divisions, materialIndex ) {\r\n\r\n\t\t\tvar step = ( to - from ) / divisions;\r\n\r\n\t\t\tpositionAttribute.setXYZ( start, 0, 0, 0 );\r\n\t\t\tcount ++;\r\n\r\n\t\t\tfor ( i = from; i < to; i += step ) {\r\n\r\n\t\t\t\tstride = start + count;\r\n\r\n\t\t\t\tpositionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );\r\n\t\t\t\tpositionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );\r\n\t\t\t\tpositionAttribute.setXYZ( stride + 2, 0, 0, 0 );\r\n\r\n\t\t\t\tcount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.addGroup( start, count, materialIndex );\r\n\r\n\t\t\tstart += count;\r\n\t\t\tcount = 0;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tgenerateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );\r\n\t\tgenerateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );\r\n\t\tgenerateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );\r\n\r\n\t\t//\r\n\r\n\t\tpositionAttribute.needsUpdate = true;\r\n\r\n\t\tif ( coneInnerAngle === coneOuterAngle ) { this.material[ 0 ].visible = false; }\r\n\r\n\t};\r\n\r\n\tPositionalAudioHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material[ 0 ].dispose();\r\n\t\tthis.material[ 1 ].dispose();\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$7 = new Vector3();\r\n\tvar _v2$5 = new Vector3();\r\n\tvar _normalMatrix$2 = new Matrix3();\r\n\r\n\tfunction FaceNormalsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\t// FaceNormalsHelper only supports THREE.Geometry\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar nNormals = 0;\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.faces.length;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconsole.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tFaceNormalsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tFaceNormalsHelper.prototype.constructor = FaceNormalsHelper;\r\n\r\n\tFaceNormalsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\t_normalMatrix$2.getNormalMatrix( this.object.matrixWorld );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tvar vertices = objGeometry.vertices;\r\n\r\n\t\tvar faces = objGeometry.faces;\r\n\r\n\t\tvar idx = 0;\r\n\r\n\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\tvar normal = face.normal;\r\n\r\n\t\t\t_v1$7.copy( vertices[ face.a ] )\r\n\t\t\t\t.add( vertices[ face.b ] )\r\n\t\t\t\t.add( vertices[ face.c ] )\r\n\t\t\t\t.divideScalar( 3 )\r\n\t\t\t\t.applyMatrix4( matrixWorld );\r\n\r\n\t\t\t_v2$5.copy( normal ).applyMatrix3( _normalMatrix$2 ).normalize().multiplyScalar( this.size ).add( _v1$7 );\r\n\r\n\t\t\tposition.setXYZ( idx, _v1$7.x, _v1$7.y, _v1$7.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t\tposition.setXYZ( idx, _v2$5.x, _v2$5.y, _v2$5.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$8 = new Vector3();\r\n\tvar _v2$6 = new Vector3();\r\n\tvar _v3$1 = new Vector3();\r\n\r\n\tfunction DirectionalLightHelper( light, size, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tif ( size === undefined ) { size = 1; }\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [\r\n\t\t\t- size, size, 0,\r\n\t\t\tsize, size, 0,\r\n\t\t\tsize, - size, 0,\r\n\t\t\t- size, - size, 0,\r\n\t\t\t- size, size, 0\r\n\t\t], 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tthis.lightPlane = new Line( geometry, material );\r\n\t\tthis.add( this.lightPlane );\r\n\r\n\t\tgeometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );\r\n\r\n\t\tthis.targetLine = new Line( geometry, material );\r\n\t\tthis.add( this.targetLine );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tDirectionalLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tDirectionalLightHelper.prototype.constructor = DirectionalLightHelper;\r\n\r\n\tDirectionalLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.lightPlane.geometry.dispose();\r\n\t\tthis.lightPlane.material.dispose();\r\n\t\tthis.targetLine.geometry.dispose();\r\n\t\tthis.targetLine.material.dispose();\r\n\r\n\t};\r\n\r\n\tDirectionalLightHelper.prototype.update = function () {\r\n\r\n\t\t_v1$8.setFromMatrixPosition( this.light.matrixWorld );\r\n\t\t_v2$6.setFromMatrixPosition( this.light.target.matrixWorld );\r\n\t\t_v3$1.subVectors( _v2$6, _v1$8 );\r\n\r\n\t\tthis.lightPlane.lookAt( _v2$6 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.lightPlane.material.color.set( this.color );\r\n\t\t\tthis.targetLine.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightPlane.material.color.copy( this.light.color );\r\n\t\t\tthis.targetLine.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t\tthis.targetLine.lookAt( _v2$6 );\r\n\t\tthis.targetLine.scale.z = _v3$1.length();\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t *\t- shows frustum, line of sight and up of the camera\r\n\t *\t- suitable for fast updates\r\n\t * \t- based on frustum visualization in lightgl.js shadowmap example\r\n\t *\t\thttp://evanw.github.com/lightgl.js/tests/shadowmap.html\r\n\t */\r\n\r\n\tvar _vector$b = new Vector3();\r\n\tvar _camera = new Camera();\r\n\r\n\tfunction CameraHelper( camera ) {\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tvar material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar pointMap = {};\r\n\r\n\t\t// colors\r\n\r\n\t\tvar colorFrustum = new Color( 0xffaa00 );\r\n\t\tvar colorCone = new Color( 0xff0000 );\r\n\t\tvar colorUp = new Color( 0x00aaff );\r\n\t\tvar colorTarget = new Color( 0xffffff );\r\n\t\tvar colorCross = new Color( 0x333333 );\r\n\r\n\t\t// near\r\n\r\n\t\taddLine( 'n1', 'n2', colorFrustum );\r\n\t\taddLine( 'n2', 'n4', colorFrustum );\r\n\t\taddLine( 'n4', 'n3', colorFrustum );\r\n\t\taddLine( 'n3', 'n1', colorFrustum );\r\n\r\n\t\t// far\r\n\r\n\t\taddLine( 'f1', 'f2', colorFrustum );\r\n\t\taddLine( 'f2', 'f4', colorFrustum );\r\n\t\taddLine( 'f4', 'f3', colorFrustum );\r\n\t\taddLine( 'f3', 'f1', colorFrustum );\r\n\r\n\t\t// sides\r\n\r\n\t\taddLine( 'n1', 'f1', colorFrustum );\r\n\t\taddLine( 'n2', 'f2', colorFrustum );\r\n\t\taddLine( 'n3', 'f3', colorFrustum );\r\n\t\taddLine( 'n4', 'f4', colorFrustum );\r\n\r\n\t\t// cone\r\n\r\n\t\taddLine( 'p', 'n1', colorCone );\r\n\t\taddLine( 'p', 'n2', colorCone );\r\n\t\taddLine( 'p', 'n3', colorCone );\r\n\t\taddLine( 'p', 'n4', colorCone );\r\n\r\n\t\t// up\r\n\r\n\t\taddLine( 'u1', 'u2', colorUp );\r\n\t\taddLine( 'u2', 'u3', colorUp );\r\n\t\taddLine( 'u3', 'u1', colorUp );\r\n\r\n\t\t// target\r\n\r\n\t\taddLine( 'c', 't', colorTarget );\r\n\t\taddLine( 'p', 'c', colorCross );\r\n\r\n\t\t// cross\r\n\r\n\t\taddLine( 'cn1', 'cn2', colorCross );\r\n\t\taddLine( 'cn3', 'cn4', colorCross );\r\n\r\n\t\taddLine( 'cf1', 'cf2', colorCross );\r\n\t\taddLine( 'cf3', 'cf4', colorCross );\r\n\r\n\t\tfunction addLine( a, b, color ) {\r\n\r\n\t\t\taddPoint( a, color );\r\n\t\t\taddPoint( b, color );\r\n\r\n\t\t}\r\n\r\n\t\tfunction addPoint( id, color ) {\r\n\r\n\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\tif ( pointMap[ id ] === undefined ) {\r\n\r\n\t\t\t\tpointMap[ id ] = [];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tpointMap[ id ].push( ( vertices.length / 3 ) - 1 );\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t\tthis.camera = camera;\r\n\t\tif ( this.camera.updateProjectionMatrix ) { this.camera.updateProjectionMatrix(); }\r\n\r\n\t\tthis.matrix = camera.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.pointMap = pointMap;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tCameraHelper.prototype = Object.create( LineSegments.prototype );\r\n\tCameraHelper.prototype.constructor = CameraHelper;\r\n\r\n\tCameraHelper.prototype.update = function () {\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar pointMap = this.pointMap;\r\n\r\n\t\tvar w = 1, h = 1;\r\n\r\n\t\t// we need just camera projection matrix inverse\r\n\t\t// world matrix must be identity\r\n\r\n\t\t_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );\r\n\r\n\t\t// center / target\r\n\r\n\t\tsetPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );\r\n\t\tsetPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );\r\n\r\n\t\t// near\r\n\r\n\t\tsetPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );\r\n\t\tsetPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );\r\n\t\tsetPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );\r\n\t\tsetPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );\r\n\r\n\t\t// far\r\n\r\n\t\tsetPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );\r\n\t\tsetPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );\r\n\t\tsetPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );\r\n\t\tsetPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );\r\n\r\n\t\t// up\r\n\r\n\t\tsetPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );\r\n\t\tsetPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );\r\n\t\tsetPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );\r\n\r\n\t\t// cross\r\n\r\n\t\tsetPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );\r\n\t\tsetPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );\r\n\t\tsetPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );\r\n\t\tsetPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );\r\n\r\n\t\tsetPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );\r\n\t\tsetPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );\r\n\t\tsetPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );\r\n\t\tsetPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );\r\n\r\n\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\r\n\r\n\t};\r\n\r\n\tfunction setPoint( point, pointMap, geometry, camera, x, y, z ) {\r\n\r\n\t\t_vector$b.set( x, y, z ).unproject( camera );\r\n\r\n\t\tvar points = pointMap[ point ];\r\n\r\n\t\tif ( points !== undefined ) {\r\n\r\n\t\t\tvar position = geometry.getAttribute( 'position' );\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tposition.setXYZ( points[ i ], _vector$b.x, _vector$b.y, _vector$b.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _box$3 = new Box3();\r\n\r\n\tfunction BoxHelper( object, color ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tif ( color === undefined ) { color = 0xffff00; }\r\n\r\n\t\tvar 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 ] );\r\n\t\tvar positions = new Float32Array( 8 * 3 );\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\r\n\t\tgeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tBoxHelper.prototype = Object.create( LineSegments.prototype );\r\n\tBoxHelper.prototype.constructor = BoxHelper;\r\n\r\n\tBoxHelper.prototype.update = function ( object ) {\r\n\r\n\t\tif ( object !== undefined ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.object !== undefined ) {\r\n\r\n\t\t\t_box$3.setFromObject( this.object );\r\n\r\n\t\t}\r\n\r\n\t\tif ( _box$3.isEmpty() ) { return; }\r\n\r\n\t\tvar min = _box$3.min;\r\n\t\tvar max = _box$3.max;\r\n\r\n\t\t/*\r\n\t\t 5____4\r\n\t\t1/___0/|\r\n\t\t| 6__|_7\r\n\t\t2/___3/\r\n\r\n\t\t0: max.x, max.y, max.z\r\n\t\t1: min.x, max.y, max.z\r\n\t\t2: min.x, min.y, max.z\r\n\t\t3: max.x, min.y, max.z\r\n\t\t4: max.x, max.y, min.z\r\n\t\t5: min.x, max.y, min.z\r\n\t\t6: min.x, min.y, min.z\r\n\t\t7: max.x, min.y, min.z\r\n\t\t*/\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\t\tvar array = position.array;\r\n\r\n\t\tarray[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;\r\n\t\tarray[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;\r\n\t\tarray[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;\r\n\t\tarray[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;\r\n\t\tarray[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;\r\n\t\tarray[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;\r\n\t\tarray[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;\r\n\t\tarray[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t\tthis.geometry.computeBoundingSphere();\r\n\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.setFromObject = function ( object ) {\r\n\r\n\t\tthis.object = object;\r\n\t\tthis.update();\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.copy = function ( source ) {\r\n\r\n\t\tLineSegments.prototype.copy.call( this, source );\r\n\r\n\t\tthis.object = source.object;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.clone = function () {\r\n\r\n\t\treturn new this.constructor().copy( this );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Box3Helper( box, color ) {\r\n\r\n\t\tthis.type = 'Box3Helper';\r\n\r\n\t\tthis.box = box;\r\n\r\n\t\tcolor = color || 0xffff00;\r\n\r\n\t\tvar 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 ] );\r\n\r\n\t\tvar 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 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\tthis.geometry.computeBoundingSphere();\r\n\r\n\t}\r\n\r\n\tBox3Helper.prototype = Object.create( LineSegments.prototype );\r\n\tBox3Helper.prototype.constructor = Box3Helper;\r\n\r\n\tBox3Helper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar box = this.box;\r\n\r\n\t\tif ( box.isEmpty() ) { return; }\r\n\r\n\t\tbox.getCenter( this.position );\r\n\r\n\t\tbox.getSize( this.scale );\r\n\r\n\t\tthis.scale.multiplyScalar( 0.5 );\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction PlaneHelper( plane, size, hex ) {\r\n\r\n\t\tthis.type = 'PlaneHelper';\r\n\r\n\t\tthis.plane = plane;\r\n\r\n\t\tthis.size = ( size === undefined ) ? 1 : size;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\r\n\r\n\t\tvar 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 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\t\tgeometry.computeBoundingSphere();\r\n\r\n\t\tLine.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\t//\r\n\r\n\t\tvar positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];\r\n\r\n\t\tvar geometry2 = new BufferGeometry();\r\n\t\tgeometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\r\n\t\tgeometry2.computeBoundingSphere();\r\n\r\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );\r\n\r\n\t}\r\n\r\n\tPlaneHelper.prototype = Object.create( Line.prototype );\r\n\tPlaneHelper.prototype.constructor = PlaneHelper;\r\n\r\n\tPlaneHelper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar scale = - this.plane.constant;\r\n\r\n\t\tif ( Math.abs( scale ) < 1e-8 ) { scale = 1e-8; } // sign does not matter\r\n\r\n\t\tthis.scale.set( 0.5 * this.size, 0.5 * this.size, scale );\r\n\r\n\t\tthis.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here\r\n\r\n\t\tthis.lookAt( this.plane.normal );\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author zz85 / http://github.com/zz85\r\n\t * @author bhouston / http://clara.io\r\n\t *\r\n\t * Creates an arrow for visualizing directions\r\n\t *\r\n\t * Parameters:\r\n\t * dir - Vector3\r\n\t * origin - Vector3\r\n\t * length - Number\r\n\t * color - color in hex value\r\n\t * headLength - Number\r\n\t * headWidth - Number\r\n\t */\r\n\r\n\tvar _axis = new Vector3();\r\n\tvar _lineGeometry, _coneGeometry;\r\n\r\n\tfunction ArrowHelper( dir, origin, length, color, headLength, headWidth ) {\r\n\r\n\t\t// dir is assumed to be normalized\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tif ( dir === undefined ) { dir = new Vector3( 0, 0, 1 ); }\r\n\t\tif ( origin === undefined ) { origin = new Vector3( 0, 0, 0 ); }\r\n\t\tif ( length === undefined ) { length = 1; }\r\n\t\tif ( color === undefined ) { color = 0xffff00; }\r\n\t\tif ( headLength === undefined ) { headLength = 0.2 * length; }\r\n\t\tif ( headWidth === undefined ) { headWidth = 0.2 * headLength; }\r\n\r\n\t\tif ( _lineGeometry === undefined ) {\r\n\r\n\t\t\t_lineGeometry = new BufferGeometry();\r\n\t\t\t_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );\r\n\r\n\t\t\t_coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );\r\n\t\t\t_coneGeometry.translate( 0, - 0.5, 0 );\r\n\r\n\t\t}\r\n\r\n\t\tthis.position.copy( origin );\r\n\r\n\t\tthis.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color } ) );\r\n\t\tthis.line.matrixAutoUpdate = false;\r\n\t\tthis.add( this.line );\r\n\r\n\t\tthis.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color } ) );\r\n\t\tthis.cone.matrixAutoUpdate = false;\r\n\t\tthis.add( this.cone );\r\n\r\n\t\tthis.setDirection( dir );\r\n\t\tthis.setLength( length, headLength, headWidth );\r\n\r\n\t}\r\n\r\n\tArrowHelper.prototype = Object.create( Object3D.prototype );\r\n\tArrowHelper.prototype.constructor = ArrowHelper;\r\n\r\n\tArrowHelper.prototype.setDirection = function ( dir ) {\r\n\r\n\t\t// dir is assumed to be normalized\r\n\r\n\t\tif ( dir.y > 0.99999 ) {\r\n\r\n\t\t\tthis.quaternion.set( 0, 0, 0, 1 );\r\n\r\n\t\t} else if ( dir.y < - 0.99999 ) {\r\n\r\n\t\t\tthis.quaternion.set( 1, 0, 0, 0 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t_axis.set( dir.z, 0, - dir.x ).normalize();\r\n\r\n\t\t\tvar radians = Math.acos( dir.y );\r\n\r\n\t\t\tthis.quaternion.setFromAxisAngle( _axis, radians );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {\r\n\r\n\t\tif ( headLength === undefined ) { headLength = 0.2 * length; }\r\n\t\tif ( headWidth === undefined ) { headWidth = 0.2 * headLength; }\r\n\r\n\t\tthis.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458\r\n\t\tthis.line.updateMatrix();\r\n\r\n\t\tthis.cone.scale.set( headWidth, headLength, headWidth );\r\n\t\tthis.cone.position.y = length;\r\n\t\tthis.cone.updateMatrix();\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.setColor = function ( color ) {\r\n\r\n\t\tthis.line.material.color.set( color );\r\n\t\tthis.cone.material.color.set( color );\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.copy = function ( source ) {\r\n\r\n\t\tObject3D.prototype.copy.call( this, source, false );\r\n\r\n\t\tthis.line.copy( source.line );\r\n\t\tthis.cone.copy( source.cone );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.clone = function () {\r\n\r\n\t\treturn new this.constructor().copy( this );\r\n\r\n\t};\n\n\t/**\r\n\t * @author sroucheray / http://sroucheray.org/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AxesHelper( size ) {\r\n\r\n\t\tsize = size || 1;\r\n\r\n\t\tvar vertices = [\r\n\t\t\t0, 0, 0,\tsize, 0, 0,\r\n\t\t\t0, 0, 0,\t0, size, 0,\r\n\t\t\t0, 0, 0,\t0, 0, size\r\n\t\t];\r\n\r\n\t\tvar colors = [\r\n\t\t\t1, 0, 0,\t1, 0.6, 0,\r\n\t\t\t0, 1, 0,\t0.6, 1, 0,\r\n\t\t\t0, 0, 1,\t0, 0.6, 1\r\n\t\t];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tAxesHelper.prototype = Object.create( LineSegments.prototype );\r\n\tAxesHelper.prototype.constructor = AxesHelper;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Face4( a, b, c, d, normal, color, materialIndex ) {\r\n\r\n\t\tconsole.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );\r\n\t\treturn new Face3( a, b, c, normal, color, materialIndex );\r\n\r\n\t}\r\n\r\n\tvar LineStrip = 0;\r\n\r\n\tvar LinePieces = 1;\r\n\r\n\tfunction MeshFaceMaterial( materials ) {\r\n\r\n\t\tconsole.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );\r\n\t\treturn materials;\r\n\r\n\t}\r\n\r\n\tfunction MultiMaterial( materials ) {\r\n\r\n\t\tif ( materials === undefined ) { materials = []; }\r\n\r\n\t\tconsole.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );\r\n\t\tmaterials.isMultiMaterial = true;\r\n\t\tmaterials.materials = materials;\r\n\t\tmaterials.clone = function () {\r\n\r\n\t\t\treturn materials.slice();\r\n\r\n\t\t};\r\n\t\treturn materials;\r\n\r\n\t}\r\n\r\n\tfunction PointCloud( geometry, material ) {\r\n\r\n\t\tconsole.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );\r\n\t\treturn new Points( geometry, material );\r\n\r\n\t}\r\n\r\n\tfunction Particle( material ) {\r\n\r\n\t\tconsole.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );\r\n\t\treturn new Sprite( material );\r\n\r\n\t}\r\n\r\n\tfunction ParticleSystem( geometry, material ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );\r\n\t\treturn new Points( geometry, material );\r\n\r\n\t}\r\n\r\n\tfunction PointCloudMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction ParticleBasicMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction ParticleSystemMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction Vertex( x, y, z ) {\r\n\r\n\t\tconsole.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );\r\n\t\treturn new Vector3( x, y, z );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction DynamicBufferAttribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );\r\n\t\treturn new BufferAttribute( array, itemSize ).setDynamic( true );\r\n\r\n\t}\r\n\r\n\tfunction Int8Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );\r\n\t\treturn new Int8BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint8Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );\r\n\t\treturn new Uint8BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint8ClampedAttribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );\r\n\t\treturn new Uint8ClampedBufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Int16Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );\r\n\t\treturn new Int16BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint16Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );\r\n\t\treturn new Uint16BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Int32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );\r\n\t\treturn new Int32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );\r\n\t\treturn new Uint32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Float32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );\r\n\t\treturn new Float32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Float64Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );\r\n\t\treturn new Float64BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tCurve.create = function ( construct, getPoint ) {\r\n\r\n\t\tconsole.log( 'THREE.Curve.create() has been deprecated' );\r\n\r\n\t\tconstruct.prototype = Object.create( Curve.prototype );\r\n\t\tconstruct.prototype.constructor = construct;\r\n\t\tconstruct.prototype.getPoint = getPoint;\r\n\r\n\t\treturn construct;\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tObject.assign( CurvePath.prototype, {\r\n\r\n\t\tcreatePointsGeometry: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\t// generate geometry from path points (for Line or Points objects)\r\n\r\n\t\t\tvar pts = this.getPoints( divisions );\r\n\t\t\treturn this.createGeometry( pts );\r\n\r\n\t\t},\r\n\r\n\t\tcreateSpacedPointsGeometry: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\t// generate geometry from equidistant sampling along the path\r\n\r\n\t\t\tvar pts = this.getSpacedPoints( divisions );\r\n\t\t\treturn this.createGeometry( pts );\r\n\r\n\t\t},\r\n\r\n\t\tcreateGeometry: function ( points ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\tvar geometry = new Geometry();\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tgeometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometry;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Path.prototype, {\r\n\r\n\t\tfromPoints: function ( points ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );\r\n\t\t\treturn this.setFromPoints( points );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction ClosedSplineCurve3( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\t\tthis.closed = true;\r\n\r\n\t}\r\n\r\n\tClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\t//\r\n\r\n\tfunction SplineCurve3( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\r\n\t}\r\n\r\n\tSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\t//\r\n\r\n\tfunction Spline( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\r\n\t}\r\n\r\n\tSpline.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\tObject.assign( Spline.prototype, {\r\n\r\n\t\tinitFromArray: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .initFromArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tgetControlPointsArray: function ( /* optionalTarget */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\treparametrizeByArcLength: function ( /* samplingCoef */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction AxisHelper( size ) {\r\n\r\n\t\tconsole.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );\r\n\t\treturn new AxesHelper( size );\r\n\r\n\t}\r\n\r\n\tfunction BoundingBoxHelper( object, color ) {\r\n\r\n\t\tconsole.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );\r\n\t\treturn new BoxHelper( object, color );\r\n\r\n\t}\r\n\r\n\tfunction EdgesHelper( object, hex ) {\r\n\r\n\t\tconsole.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );\r\n\t\treturn new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\r\n\r\n\t}\r\n\r\n\tGridHelper.prototype.setColors = function () {\r\n\r\n\t\tconsole.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );\r\n\r\n\t};\r\n\r\n\tSkeletonHelper.prototype.update = function () {\r\n\r\n\t\tconsole.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );\r\n\r\n\t};\r\n\r\n\tfunction WireframeHelper( object, hex ) {\r\n\r\n\t\tconsole.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );\r\n\t\treturn new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tObject.assign( Loader.prototype, {\r\n\r\n\t\textractUrlBase: function ( url ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );\r\n\t\t\treturn LoaderUtils.extractUrlBase( url );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tLoader.Handlers = {\r\n\r\n\t\tadd: function ( /* regex, loader */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );\r\n\r\n\t\t},\r\n\r\n\t\tget: function ( /* file */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tfunction XHRLoader( manager ) {\r\n\r\n\t\tconsole.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );\r\n\t\treturn new FileLoader( manager );\r\n\r\n\t}\r\n\r\n\tfunction BinaryTextureLoader( manager ) {\r\n\r\n\t\tconsole.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );\r\n\t\treturn new DataTextureLoader( manager );\r\n\r\n\t}\r\n\r\n\tObject.assign( ObjectLoader.prototype, {\r\n\r\n\t\tsetTexturePath: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );\r\n\t\t\treturn this.setResourcePath( value );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Box2.prototype, {\r\n\r\n\t\tcenter: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );\r\n\t\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t\t},\r\n\t\tempty: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );\r\n\t\t\treturn this.isEmpty();\r\n\r\n\t\t},\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tsize: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );\r\n\t\t\treturn this.getSize( optionalTarget );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.assign( Box3.prototype, {\r\n\r\n\t\tcenter: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );\r\n\t\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t\t},\r\n\t\tempty: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );\r\n\t\t\treturn this.isEmpty();\r\n\r\n\t\t},\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tisIntersectionSphere: function ( sphere ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\r\n\t\t\treturn this.intersectsSphere( sphere );\r\n\r\n\t\t},\r\n\t\tsize: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );\r\n\t\t\treturn this.getSize( optionalTarget );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tLine3.prototype.center = function ( optionalTarget ) {\r\n\r\n\t\tconsole.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );\r\n\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t};\r\n\r\n\tObject.assign( _Math, {\r\n\r\n\t\trandom16: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );\r\n\t\t\treturn Math.random();\r\n\r\n\t\t},\r\n\r\n\t\tnearestPowerOfTwo: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );\r\n\t\t\treturn _Math.floorPowerOfTwo( value );\r\n\r\n\t\t},\r\n\r\n\t\tnextPowerOfTwo: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );\r\n\t\t\treturn _Math.ceilPowerOfTwo( value );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Matrix3.prototype, {\r\n\r\n\t\tflattenToArrayOffset: function ( array, offset ) {\r\n\r\n\t\t\tconsole.warn( \"THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\r\n\t\t\treturn this.toArray( array, offset );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix3( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3Array: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\tapplyToBuffer: function ( buffer /*, offset, length */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\r\n\t\t\treturn this.applyToBufferAttribute( buffer );\r\n\r\n\t\t},\r\n\t\tapplyToVector3Array: function ( /* array, offset, length */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Matrix4.prototype, {\r\n\r\n\t\textractPosition: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );\r\n\t\t\treturn this.copyPosition( m );\r\n\r\n\t\t},\r\n\t\tflattenToArrayOffset: function ( array, offset ) {\r\n\r\n\t\t\tconsole.warn( \"THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\r\n\t\t\treturn this.toArray( array, offset );\r\n\r\n\t\t},\r\n\t\tgetPosition: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );\r\n\t\t\treturn new Vector3().setFromMatrixColumn( this, 3 );\r\n\r\n\t\t},\r\n\t\tsetRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );\r\n\t\t\treturn this.makeRotationFromQuaternion( q );\r\n\r\n\t\t},\r\n\t\tmultiplyToArray: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector4: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3Array: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateAxis: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );\r\n\t\t\tv.transformDirection( this );\r\n\r\n\t\t},\r\n\t\tcrossVector: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\ttranslate: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .translate() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateX: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateX() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateY: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateY() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateZ: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateZ() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateByAxis: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );\r\n\r\n\t\t},\r\n\t\tapplyToBuffer: function ( buffer /*, offset, length */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\r\n\t\t\treturn this.applyToBufferAttribute( buffer );\r\n\r\n\t\t},\r\n\t\tapplyToVector3Array: function ( /* array, offset, length */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\tmakeFrustum: function ( left, right, bottom, top, near, far ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );\r\n\t\t\treturn this.makePerspective( left, right, top, bottom, near, far );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tPlane.prototype.isIntersectionLine = function ( line ) {\r\n\r\n\t\tconsole.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );\r\n\t\treturn this.intersectsLine( line );\r\n\r\n\t};\r\n\r\n\tQuaternion.prototype.multiplyVector3 = function ( vector ) {\r\n\r\n\t\tconsole.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );\r\n\t\treturn vector.applyQuaternion( this );\r\n\r\n\t};\r\n\r\n\tObject.assign( Ray.prototype, {\r\n\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tisIntersectionPlane: function ( plane ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );\r\n\t\t\treturn this.intersectsPlane( plane );\r\n\r\n\t\t},\r\n\t\tisIntersectionSphere: function ( sphere ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\r\n\t\t\treturn this.intersectsSphere( sphere );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle.prototype, {\r\n\r\n\t\tarea: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );\r\n\t\t\treturn this.getArea();\r\n\r\n\t\t},\r\n\t\tbarycoordFromPoint: function ( point, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\r\n\t\t\treturn this.getBarycoord( point, target );\r\n\r\n\t\t},\r\n\t\tmidpoint: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );\r\n\t\t\treturn this.getMidpoint( target );\r\n\r\n\t\t},\r\n\t\tnormal: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\r\n\t\t\treturn this.getNormal( target );\r\n\r\n\t\t},\r\n\t\tplane: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );\r\n\t\t\treturn this.getPlane( target );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle, {\r\n\r\n\t\tbarycoordFromPoint: function ( point, a, b, c, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\r\n\t\t\treturn Triangle.getBarycoord( point, a, b, c, target );\r\n\r\n\t\t},\r\n\t\tnormal: function ( a, b, c, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\r\n\t\t\treturn Triangle.getNormal( a, b, c, target );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Shape.prototype, {\r\n\r\n\t\textractAllPoints: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );\r\n\t\t\treturn this.extractPoints( divisions );\r\n\r\n\t\t},\r\n\t\textrude: function ( options ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );\r\n\t\t\treturn new ExtrudeGeometry( this, options );\r\n\r\n\t\t},\r\n\t\tmakeGeometry: function ( options ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );\r\n\t\t\treturn new ShapeGeometry( this, options );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector2.prototype, {\r\n\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tdistanceToManhattan: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\r\n\t\t\treturn this.manhattanDistanceTo( v );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector3.prototype, {\r\n\r\n\t\tsetEulerFromRotationMatrix: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );\r\n\r\n\t\t},\r\n\t\tsetEulerFromQuaternion: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );\r\n\r\n\t\t},\r\n\t\tgetPositionFromMatrix: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );\r\n\t\t\treturn this.setFromMatrixPosition( m );\r\n\r\n\t\t},\r\n\t\tgetScaleFromMatrix: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );\r\n\t\t\treturn this.setFromMatrixScale( m );\r\n\r\n\t\t},\r\n\t\tgetColumnFromMatrix: function ( index, matrix ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );\r\n\t\t\treturn this.setFromMatrixColumn( matrix, index );\r\n\r\n\t\t},\r\n\t\tapplyProjection: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );\r\n\t\t\treturn this.applyMatrix4( m );\r\n\r\n\t\t},\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tdistanceToManhattan: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\r\n\t\t\treturn this.manhattanDistanceTo( v );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector4.prototype, {\r\n\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Geometry.prototype, {\r\n\r\n\t\tcomputeTangents: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Geometry: .computeTangents() has been removed.' );\r\n\r\n\t\t},\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Object3D.prototype, {\r\n\r\n\t\tgetChildByName: function ( name ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );\r\n\t\t\treturn this.getObjectByName( name );\r\n\r\n\t\t},\r\n\t\trenderDepth: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );\r\n\r\n\t\t},\r\n\t\ttranslate: function ( distance, axis ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );\r\n\t\t\treturn this.translateOnAxis( axis, distance );\r\n\r\n\t\t},\r\n\t\tgetWorldRotation: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Object3D.prototype, {\r\n\r\n\t\teulerOrder: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\r\n\t\t\t\treturn this.rotation.order;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\r\n\t\t\t\tthis.rotation.order = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tuseQuaternion: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Mesh.prototype, {\r\n\r\n\t\tsetDrawMode: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );\r\n\r\n\t\t},\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Mesh.prototype, {\r\n\r\n\t\tdrawMode: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );\r\n\t\t\t\treturn TrianglesDrawMode;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( LOD.prototype, {\r\n\r\n\t\tobjects: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.LOD: .objects has been renamed to .levels.' );\r\n\t\t\t\treturn this.levels;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Skeleton.prototype, 'useVertexTexture', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\r\n\r\n\t\t},\r\n\t\tset: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tSkinnedMesh.prototype.initBones = function () {\r\n\r\n\t\tconsole.error( 'THREE.SkinnedMesh: initBones() has been removed.' );\r\n\r\n\t};\r\n\r\n\tObject.defineProperty( Curve.prototype, '__arcLengthDivisions', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\r\n\t\t\treturn this.arcLengthDivisions;\r\n\r\n\t\t},\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\r\n\t\t\tthis.arcLengthDivisions = value;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tPerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {\r\n\r\n\t\tconsole.warn( \"THREE.PerspectiveCamera.setLens is deprecated. \" +\r\n\t\t\t\t\"Use .setFocalLength and .filmGauge for a photographic setup.\" );\r\n\r\n\t\tif ( filmGauge !== undefined ) { this.filmGauge = filmGauge; }\r\n\t\tthis.setFocalLength( focalLength );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Light.prototype, {\r\n\t\tonlyShadow: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .onlyShadow has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraFov: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );\r\n\t\t\t\tthis.shadow.camera.fov = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraLeft: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );\r\n\t\t\t\tthis.shadow.camera.left = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraRight: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );\r\n\t\t\t\tthis.shadow.camera.right = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraTop: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );\r\n\t\t\t\tthis.shadow.camera.top = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraBottom: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );\r\n\t\t\t\tthis.shadow.camera.bottom = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraNear: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );\r\n\t\t\t\tthis.shadow.camera.near = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraFar: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );\r\n\t\t\t\tthis.shadow.camera.far = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraVisible: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowBias: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );\r\n\t\t\t\tthis.shadow.bias = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowDarkness: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowDarkness has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapWidth: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );\r\n\t\t\t\tthis.shadow.mapSize.width = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapHeight: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );\r\n\t\t\t\tthis.shadow.mapSize.height = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( BufferAttribute.prototype, {\r\n\r\n\t\tlength: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );\r\n\t\t\t\treturn this.array.length;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tdynamic: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );\r\n\t\t\t\treturn this.usage === DynamicDrawUsage;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );\r\n\t\t\t\tthis.setUsage( DynamicDrawUsage );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( BufferAttribute.prototype, {\r\n\t\tsetDynamic: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );\r\n\t\t\tthis.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\t\tcopyIndicesArray: function ( /* indices */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetArray: function ( /* array */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.assign( BufferGeometry.prototype, {\r\n\r\n\t\taddIndex: function ( index ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );\r\n\t\t\tthis.setIndex( index );\r\n\r\n\t\t},\r\n\t\taddAttribute: function ( name, attribute ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );\r\n\r\n\t\t\tif ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );\r\n\r\n\t\t\t\treturn this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( name === 'index' ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );\r\n\t\t\t\tthis.setIndex( attribute );\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.setAttribute( name, attribute );\r\n\r\n\t\t},\r\n\t\taddDrawCall: function ( start, count, indexOffset ) {\r\n\r\n\t\t\tif ( indexOffset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );\r\n\r\n\t\t\t}\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );\r\n\t\t\tthis.addGroup( start, count );\r\n\r\n\t\t},\r\n\t\tclearDrawCalls: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );\r\n\t\t\tthis.clearGroups();\r\n\r\n\t\t},\r\n\t\tcomputeTangents: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );\r\n\r\n\t\t},\r\n\t\tcomputeOffsets: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );\r\n\r\n\t\t},\r\n\t\tremoveAttribute: function ( name ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );\r\n\r\n\t\t\treturn this.deleteAttribute( name );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.defineProperties( BufferGeometry.prototype, {\r\n\r\n\t\tdrawcalls: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );\r\n\t\t\t\treturn this.groups;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\toffsets: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );\r\n\t\t\t\treturn this.groups;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( InterleavedBuffer.prototype, {\r\n\r\n\t\tdynamic: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );\r\n\t\t\t\treturn this.usage === DynamicDrawUsage;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );\r\n\t\t\t\tthis.setUsage( value );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBuffer.prototype, {\r\n\t\tsetDynamic: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );\r\n\t\t\tthis.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\t\tsetArray: function ( /* array */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( ExtrudeBufferGeometry.prototype, {\r\n\r\n\t\tgetArrays: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );\r\n\r\n\t\t},\r\n\r\n\t\taddShapeList: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );\r\n\r\n\t\t},\r\n\r\n\t\taddShape: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Uniform.prototype, {\r\n\r\n\t\tdynamic: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tonUpdate: {\r\n\t\t\tvalue: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Material.prototype, {\r\n\r\n\t\twrapAround: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\toverdraw: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\twrapRGB: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapRGB has been removed.' );\r\n\t\t\t\treturn new Color();\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tshading: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\t\t\t\tthis.flatShading = ( value === FlatShading );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tstencilMask: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );\r\n\t\t\t\treturn this.stencilFuncMask;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );\r\n\t\t\t\tthis.stencilFuncMask = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( MeshPhongMaterial.prototype, {\r\n\r\n\t\tmetal: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( ShaderMaterial.prototype, {\r\n\r\n\t\tderivatives: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\r\n\t\t\t\treturn this.extensions.derivatives;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\r\n\t\t\t\tthis.extensions.derivatives = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( WebGLRenderer.prototype, {\r\n\r\n\t\tclearTarget: function ( renderTarget, color, depth, stencil ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );\r\n\t\t\tthis.setRenderTarget( renderTarget );\r\n\t\t\tthis.clear( color, depth, stencil );\r\n\r\n\t\t},\r\n\t\tanimate: function ( callback ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );\r\n\t\t\tthis.setAnimationLoop( callback );\r\n\r\n\t\t},\r\n\t\tgetCurrentRenderTarget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );\r\n\t\t\treturn this.getRenderTarget();\r\n\r\n\t\t},\r\n\t\tgetMaxAnisotropy: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );\r\n\t\t\treturn this.capabilities.getMaxAnisotropy();\r\n\r\n\t\t},\r\n\t\tgetPrecision: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );\r\n\t\t\treturn this.capabilities.precision;\r\n\r\n\t\t},\r\n\t\tresetGLState: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );\r\n\t\t\treturn this.state.reset();\r\n\r\n\t\t},\r\n\t\tsupportsFloatTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \\'OES_texture_float\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_texture_float' );\r\n\r\n\t\t},\r\n\t\tsupportsHalfFloatTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \\'OES_texture_half_float\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_texture_half_float' );\r\n\r\n\t\t},\r\n\t\tsupportsStandardDerivatives: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \\'OES_standard_derivatives\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_standard_derivatives' );\r\n\r\n\t\t},\r\n\t\tsupportsCompressedTextureS3TC: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \\'WEBGL_compressed_texture_s3tc\\' ).' );\r\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_s3tc' );\r\n\r\n\t\t},\r\n\t\tsupportsCompressedTexturePVRTC: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \\'WEBGL_compressed_texture_pvrtc\\' ).' );\r\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );\r\n\r\n\t\t},\r\n\t\tsupportsBlendMinMax: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \\'EXT_blend_minmax\\' ).' );\r\n\t\t\treturn this.extensions.get( 'EXT_blend_minmax' );\r\n\r\n\t\t},\r\n\t\tsupportsVertexTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );\r\n\t\t\treturn this.capabilities.vertexTextures;\r\n\r\n\t\t},\r\n\t\tsupportsInstancedArrays: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \\'ANGLE_instanced_arrays\\' ).' );\r\n\t\t\treturn this.extensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t},\r\n\t\tenableScissorTest: function ( boolean ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );\r\n\t\t\tthis.setScissorTest( boolean );\r\n\r\n\t\t},\r\n\t\tinitMaterial: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );\r\n\r\n\t\t},\r\n\t\taddPrePlugin: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );\r\n\r\n\t\t},\r\n\t\taddPostPlugin: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );\r\n\r\n\t\t},\r\n\t\tupdateShadowMap: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetFaceCulling: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );\r\n\r\n\t\t},\r\n\t\tallocTextureUnit: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetTexture: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetTextureCube: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );\r\n\r\n\t\t},\r\n\t\tgetActiveMipMapLevel: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );\r\n\t\t\treturn this.getActiveMipmapLevel();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( WebGLRenderer.prototype, {\r\n\r\n\t\tshadowMapEnabled: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.shadowMap.enabled;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );\r\n\t\t\t\tthis.shadowMap.enabled = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapType: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.shadowMap.type;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );\r\n\t\t\t\tthis.shadowMap.type = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapCullFace: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tcontext: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );\r\n\t\t\t\treturn this.getContext();\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tvr: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .vr has been removed. Use .xr instead.' );\r\n\t\t\t\treturn this.xr;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tgammaInput: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Please define the correct color spaces for textures via Texture.encoding instead.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Please define the correct color spaces for textures via Texture.encoding instead.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( WebGLShadowMap.prototype, {\r\n\r\n\t\tcullFace: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* cullFace */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trenderReverseSided: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trenderSingleSided: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebGLRenderTargetCube.prototype, {\r\n\r\n\t\tactiveCubeFace: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeCubeFace has been removed. It is now the second parameter of WebGLRenderer.setRenderTarget().' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tactiveMipMapLevel: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeMipMapLevel has been removed. It is now the third parameter of WebGLRenderer.setRenderTarget().' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebGLRenderTarget.prototype, {\r\n\r\n\t\twrapS: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\r\n\t\t\t\treturn this.texture.wrapS;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\r\n\t\t\t\tthis.texture.wrapS = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\twrapT: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\r\n\t\t\t\treturn this.texture.wrapT;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\r\n\t\t\t\tthis.texture.wrapT = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tmagFilter: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\r\n\t\t\t\treturn this.texture.magFilter;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\r\n\t\t\t\tthis.texture.magFilter = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tminFilter: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\r\n\t\t\t\treturn this.texture.minFilter;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\r\n\t\t\t\tthis.texture.minFilter = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tanisotropy: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\r\n\t\t\t\treturn this.texture.anisotropy;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\r\n\t\t\t\tthis.texture.anisotropy = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\toffset: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\r\n\t\t\t\treturn this.texture.offset;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\r\n\t\t\t\tthis.texture.offset = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trepeat: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\r\n\t\t\t\treturn this.texture.repeat;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\r\n\t\t\t\tthis.texture.repeat = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tformat: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\r\n\t\t\t\treturn this.texture.format;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\r\n\t\t\t\tthis.texture.format = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\ttype: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\r\n\t\t\t\treturn this.texture.type;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\r\n\t\t\t\tthis.texture.type = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tgenerateMipmaps: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\r\n\t\t\t\treturn this.texture.generateMipmaps;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\r\n\t\t\t\tthis.texture.generateMipmaps = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebVRManager.prototype, {\r\n\r\n\t\tstanding: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .standing has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tuserHeight: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .userHeight has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Audio.prototype, {\r\n\r\n\t\tload: {\r\n\t\t\tvalue: function ( file ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );\r\n\t\t\t\tvar scope = this;\r\n\t\t\t\tvar audioLoader = new AudioLoader();\r\n\t\t\t\taudioLoader.load( file, function ( buffer ) {\r\n\r\n\t\t\t\t\tscope.setBuffer( buffer );\r\n\r\n\t\t\t\t} );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tstartTime: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: .startTime is now .play( delay ).' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tAudioAnalyser.prototype.getData = function () {\r\n\r\n\t\tconsole.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );\r\n\t\treturn this.getFrequencyData();\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tCubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {\r\n\r\n\t\tconsole.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );\r\n\t\treturn this.update( renderer, scene );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar GeometryUtils = {\r\n\r\n\t\tmerge: function ( geometry1, geometry2, materialIndexOffset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );\r\n\t\t\tvar matrix;\r\n\r\n\t\t\tif ( geometry2.isMesh ) {\r\n\r\n\t\t\t\tgeometry2.matrixAutoUpdate && geometry2.updateMatrix();\r\n\r\n\t\t\t\tmatrix = geometry2.matrix;\r\n\t\t\t\tgeometry2 = geometry2.geometry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry1.merge( geometry2, matrix, materialIndexOffset );\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function ( geometry ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );\r\n\t\t\treturn geometry.center();\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tImageUtils.crossOrigin = undefined;\r\n\r\n\tImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {\r\n\r\n\t\tconsole.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );\r\n\r\n\t\tvar loader = new TextureLoader();\r\n\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\tvar texture = loader.load( url, onLoad, undefined, onError );\r\n\r\n\t\tif ( mapping ) { texture.mapping = mapping; }\r\n\r\n\t\treturn texture;\r\n\r\n\t};\r\n\r\n\tImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {\r\n\r\n\t\tconsole.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );\r\n\r\n\t\tvar loader = new CubeTextureLoader();\r\n\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\tvar texture = loader.load( urls, onLoad, undefined, onError );\r\n\r\n\t\tif ( mapping ) { texture.mapping = mapping; }\r\n\r\n\t\treturn texture;\r\n\r\n\t};\r\n\r\n\tImageUtils.loadCompressedTexture = function () {\r\n\r\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );\r\n\r\n\t};\r\n\r\n\tImageUtils.loadCompressedTextureCube = function () {\r\n\r\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction CanvasRenderer() {\r\n\r\n\t\tconsole.error( 'THREE.CanvasRenderer has been removed' );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction JSONLoader() {\r\n\r\n\t\tconsole.error( 'THREE.JSONLoader has been removed.' );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tvar SceneUtils = {\r\n\r\n\t\tcreateMultiMaterialObject: function ( /* geometry, materials */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t},\r\n\r\n\t\tdetach: function ( /* child, parent, scene */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t},\r\n\r\n\t\tattach: function ( /* child, scene, parent */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction LensFlare() {\r\n\r\n\t\tconsole.error( 'THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js' );\r\n\r\n\t}\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t/* eslint-disable no-undef */\r\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {\r\n\t\t\trevision: REVISION,\r\n\t\t} } ) );\r\n\t\t/* eslint-enable no-undef */\r\n\r\n\t}\n\n\texports.ACESFilmicToneMapping = ACESFilmicToneMapping;\n\texports.AddEquation = AddEquation;\n\texports.AddOperation = AddOperation;\n\texports.AdditiveBlending = AdditiveBlending;\n\texports.AlphaFormat = AlphaFormat;\n\texports.AlwaysDepth = AlwaysDepth;\n\texports.AlwaysStencilFunc = AlwaysStencilFunc;\n\texports.AmbientLight = AmbientLight;\n\texports.AmbientLightProbe = AmbientLightProbe;\n\texports.AnimationClip = AnimationClip;\n\texports.AnimationLoader = AnimationLoader;\n\texports.AnimationMixer = AnimationMixer;\n\texports.AnimationObjectGroup = AnimationObjectGroup;\n\texports.AnimationUtils = AnimationUtils;\n\texports.ArcCurve = ArcCurve;\n\texports.ArrayCamera = ArrayCamera;\n\texports.ArrowHelper = ArrowHelper;\n\texports.Audio = Audio;\n\texports.AudioAnalyser = AudioAnalyser;\n\texports.AudioContext = AudioContext;\n\texports.AudioListener = AudioListener;\n\texports.AudioLoader = AudioLoader;\n\texports.AxesHelper = AxesHelper;\n\texports.AxisHelper = AxisHelper;\n\texports.BackSide = BackSide;\n\texports.BasicDepthPacking = BasicDepthPacking;\n\texports.BasicShadowMap = BasicShadowMap;\n\texports.BinaryTextureLoader = BinaryTextureLoader;\n\texports.Bone = Bone;\n\texports.BooleanKeyframeTrack = BooleanKeyframeTrack;\n\texports.BoundingBoxHelper = BoundingBoxHelper;\n\texports.Box2 = Box2;\n\texports.Box3 = Box3;\n\texports.Box3Helper = Box3Helper;\n\texports.BoxBufferGeometry = BoxBufferGeometry;\n\texports.BoxGeometry = BoxGeometry;\n\texports.BoxHelper = BoxHelper;\n\texports.BufferAttribute = BufferAttribute;\n\texports.BufferGeometry = BufferGeometry;\n\texports.BufferGeometryLoader = BufferGeometryLoader;\n\texports.ByteType = ByteType;\n\texports.Cache = Cache;\n\texports.Camera = Camera;\n\texports.CameraHelper = CameraHelper;\n\texports.CanvasRenderer = CanvasRenderer;\n\texports.CanvasTexture = CanvasTexture;\n\texports.CatmullRomCurve3 = CatmullRomCurve3;\n\texports.CineonToneMapping = CineonToneMapping;\n\texports.CircleBufferGeometry = CircleBufferGeometry;\n\texports.CircleGeometry = CircleGeometry;\n\texports.ClampToEdgeWrapping = ClampToEdgeWrapping;\n\texports.Clock = Clock;\n\texports.ClosedSplineCurve3 = ClosedSplineCurve3;\n\texports.Color = Color;\n\texports.ColorKeyframeTrack = ColorKeyframeTrack;\n\texports.CompressedTexture = CompressedTexture;\n\texports.CompressedTextureLoader = CompressedTextureLoader;\n\texports.ConeBufferGeometry = ConeBufferGeometry;\n\texports.ConeGeometry = ConeGeometry;\n\texports.CubeCamera = CubeCamera;\n\texports.CubeGeometry = BoxGeometry;\n\texports.CubeReflectionMapping = CubeReflectionMapping;\n\texports.CubeRefractionMapping = CubeRefractionMapping;\n\texports.CubeTexture = CubeTexture;\n\texports.CubeTextureLoader = CubeTextureLoader;\n\texports.CubeUVReflectionMapping = CubeUVReflectionMapping;\n\texports.CubeUVRefractionMapping = CubeUVRefractionMapping;\n\texports.CubicBezierCurve = CubicBezierCurve;\n\texports.CubicBezierCurve3 = CubicBezierCurve3;\n\texports.CubicInterpolant = CubicInterpolant;\n\texports.CullFaceBack = CullFaceBack;\n\texports.CullFaceFront = CullFaceFront;\n\texports.CullFaceFrontBack = CullFaceFrontBack;\n\texports.CullFaceNone = CullFaceNone;\n\texports.Curve = Curve;\n\texports.CurvePath = CurvePath;\n\texports.CustomBlending = CustomBlending;\n\texports.CylinderBufferGeometry = CylinderBufferGeometry;\n\texports.CylinderGeometry = CylinderGeometry;\n\texports.Cylindrical = Cylindrical;\n\texports.DataTexture = DataTexture;\n\texports.DataTexture2DArray = DataTexture2DArray;\n\texports.DataTexture3D = DataTexture3D;\n\texports.DataTextureLoader = DataTextureLoader;\n\texports.DecrementStencilOp = DecrementStencilOp;\n\texports.DecrementWrapStencilOp = DecrementWrapStencilOp;\n\texports.DefaultLoadingManager = DefaultLoadingManager;\n\texports.DepthFormat = DepthFormat;\n\texports.DepthStencilFormat = DepthStencilFormat;\n\texports.DepthTexture = DepthTexture;\n\texports.DirectionalLight = DirectionalLight;\n\texports.DirectionalLightHelper = DirectionalLightHelper;\n\texports.DirectionalLightShadow = DirectionalLightShadow;\n\texports.DiscreteInterpolant = DiscreteInterpolant;\n\texports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;\n\texports.DodecahedronGeometry = DodecahedronGeometry;\n\texports.DoubleSide = DoubleSide;\n\texports.DstAlphaFactor = DstAlphaFactor;\n\texports.DstColorFactor = DstColorFactor;\n\texports.DynamicBufferAttribute = DynamicBufferAttribute;\n\texports.DynamicCopyUsage = DynamicCopyUsage;\n\texports.DynamicDrawUsage = DynamicDrawUsage;\n\texports.DynamicReadUsage = DynamicReadUsage;\n\texports.EdgesGeometry = EdgesGeometry;\n\texports.EdgesHelper = EdgesHelper;\n\texports.EllipseCurve = EllipseCurve;\n\texports.EqualDepth = EqualDepth;\n\texports.EqualStencilFunc = EqualStencilFunc;\n\texports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;\n\texports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;\n\texports.Euler = Euler;\n\texports.EventDispatcher = EventDispatcher;\n\texports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;\n\texports.ExtrudeGeometry = ExtrudeGeometry;\n\texports.Face3 = Face3;\n\texports.Face4 = Face4;\n\texports.FaceColors = FaceColors;\n\texports.FaceNormalsHelper = FaceNormalsHelper;\n\texports.FileLoader = FileLoader;\n\texports.FlatShading = FlatShading;\n\texports.Float32Attribute = Float32Attribute;\n\texports.Float32BufferAttribute = Float32BufferAttribute;\n\texports.Float64Attribute = Float64Attribute;\n\texports.Float64BufferAttribute = Float64BufferAttribute;\n\texports.FloatType = FloatType;\n\texports.Fog = Fog;\n\texports.FogExp2 = FogExp2;\n\texports.Font = Font;\n\texports.FontLoader = FontLoader;\n\texports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;\n\texports.FrontFaceDirectionCW = FrontFaceDirectionCW;\n\texports.FrontSide = FrontSide;\n\texports.Frustum = Frustum;\n\texports.GammaEncoding = GammaEncoding;\n\texports.Geometry = Geometry;\n\texports.GeometryUtils = GeometryUtils;\n\texports.GreaterDepth = GreaterDepth;\n\texports.GreaterEqualDepth = GreaterEqualDepth;\n\texports.GreaterEqualStencilFunc = GreaterEqualStencilFunc;\n\texports.GreaterStencilFunc = GreaterStencilFunc;\n\texports.GridHelper = GridHelper;\n\texports.Group = Group;\n\texports.HalfFloatType = HalfFloatType;\n\texports.HemisphereLight = HemisphereLight;\n\texports.HemisphereLightHelper = HemisphereLightHelper;\n\texports.HemisphereLightProbe = HemisphereLightProbe;\n\texports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;\n\texports.IcosahedronGeometry = IcosahedronGeometry;\n\texports.ImageBitmapLoader = ImageBitmapLoader;\n\texports.ImageLoader = ImageLoader;\n\texports.ImageUtils = ImageUtils;\n\texports.ImmediateRenderObject = ImmediateRenderObject;\n\texports.IncrementStencilOp = IncrementStencilOp;\n\texports.IncrementWrapStencilOp = IncrementWrapStencilOp;\n\texports.InstancedBufferAttribute = InstancedBufferAttribute;\n\texports.InstancedBufferGeometry = InstancedBufferGeometry;\n\texports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;\n\texports.InstancedMesh = InstancedMesh;\n\texports.Int16Attribute = Int16Attribute;\n\texports.Int16BufferAttribute = Int16BufferAttribute;\n\texports.Int32Attribute = Int32Attribute;\n\texports.Int32BufferAttribute = Int32BufferAttribute;\n\texports.Int8Attribute = Int8Attribute;\n\texports.Int8BufferAttribute = Int8BufferAttribute;\n\texports.IntType = IntType;\n\texports.InterleavedBuffer = InterleavedBuffer;\n\texports.InterleavedBufferAttribute = InterleavedBufferAttribute;\n\texports.Interpolant = Interpolant;\n\texports.InterpolateDiscrete = InterpolateDiscrete;\n\texports.InterpolateLinear = InterpolateLinear;\n\texports.InterpolateSmooth = InterpolateSmooth;\n\texports.InvertStencilOp = InvertStencilOp;\n\texports.JSONLoader = JSONLoader;\n\texports.KeepStencilOp = KeepStencilOp;\n\texports.KeyframeTrack = KeyframeTrack;\n\texports.LOD = LOD;\n\texports.LatheBufferGeometry = LatheBufferGeometry;\n\texports.LatheGeometry = LatheGeometry;\n\texports.Layers = Layers;\n\texports.LensFlare = LensFlare;\n\texports.LessDepth = LessDepth;\n\texports.LessEqualDepth = LessEqualDepth;\n\texports.LessEqualStencilFunc = LessEqualStencilFunc;\n\texports.LessStencilFunc = LessStencilFunc;\n\texports.Light = Light;\n\texports.LightProbe = LightProbe;\n\texports.LightProbeHelper = LightProbeHelper;\n\texports.LightShadow = LightShadow;\n\texports.Line = Line;\n\texports.Line3 = Line3;\n\texports.LineBasicMaterial = LineBasicMaterial;\n\texports.LineCurve = LineCurve;\n\texports.LineCurve3 = LineCurve3;\n\texports.LineDashedMaterial = LineDashedMaterial;\n\texports.LineLoop = LineLoop;\n\texports.LinePieces = LinePieces;\n\texports.LineSegments = LineSegments;\n\texports.LineStrip = LineStrip;\n\texports.LinearEncoding = LinearEncoding;\n\texports.LinearFilter = LinearFilter;\n\texports.LinearInterpolant = LinearInterpolant;\n\texports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;\n\texports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;\n\texports.LinearMipmapLinearFilter = LinearMipmapLinearFilter;\n\texports.LinearMipmapNearestFilter = LinearMipmapNearestFilter;\n\texports.LinearToneMapping = LinearToneMapping;\n\texports.Loader = Loader;\n\texports.LoaderUtils = LoaderUtils;\n\texports.LoadingManager = LoadingManager;\n\texports.LogLuvEncoding = LogLuvEncoding;\n\texports.LoopOnce = LoopOnce;\n\texports.LoopPingPong = LoopPingPong;\n\texports.LoopRepeat = LoopRepeat;\n\texports.LuminanceAlphaFormat = LuminanceAlphaFormat;\n\texports.LuminanceFormat = LuminanceFormat;\n\texports.MOUSE = MOUSE;\n\texports.Material = Material;\n\texports.MaterialLoader = MaterialLoader;\n\texports.Math = _Math;\n\texports.Matrix3 = Matrix3;\n\texports.Matrix4 = Matrix4;\n\texports.MaxEquation = MaxEquation;\n\texports.Mesh = Mesh;\n\texports.MeshBasicMaterial = MeshBasicMaterial;\n\texports.MeshDepthMaterial = MeshDepthMaterial;\n\texports.MeshDistanceMaterial = MeshDistanceMaterial;\n\texports.MeshFaceMaterial = MeshFaceMaterial;\n\texports.MeshLambertMaterial = MeshLambertMaterial;\n\texports.MeshMatcapMaterial = MeshMatcapMaterial;\n\texports.MeshNormalMaterial = MeshNormalMaterial;\n\texports.MeshPhongMaterial = MeshPhongMaterial;\n\texports.MeshPhysicalMaterial = MeshPhysicalMaterial;\n\texports.MeshStandardMaterial = MeshStandardMaterial;\n\texports.MeshToonMaterial = MeshToonMaterial;\n\texports.MinEquation = MinEquation;\n\texports.MirroredRepeatWrapping = MirroredRepeatWrapping;\n\texports.MixOperation = MixOperation;\n\texports.MultiMaterial = MultiMaterial;\n\texports.MultiplyBlending = MultiplyBlending;\n\texports.MultiplyOperation = MultiplyOperation;\n\texports.NearestFilter = NearestFilter;\n\texports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;\n\texports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;\n\texports.NearestMipmapLinearFilter = NearestMipmapLinearFilter;\n\texports.NearestMipmapNearestFilter = NearestMipmapNearestFilter;\n\texports.NeverDepth = NeverDepth;\n\texports.NeverStencilFunc = NeverStencilFunc;\n\texports.NoBlending = NoBlending;\n\texports.NoColors = NoColors;\n\texports.NoToneMapping = NoToneMapping;\n\texports.NormalBlending = NormalBlending;\n\texports.NotEqualDepth = NotEqualDepth;\n\texports.NotEqualStencilFunc = NotEqualStencilFunc;\n\texports.NumberKeyframeTrack = NumberKeyframeTrack;\n\texports.Object3D = Object3D;\n\texports.ObjectLoader = ObjectLoader;\n\texports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;\n\texports.OctahedronBufferGeometry = OctahedronBufferGeometry;\n\texports.OctahedronGeometry = OctahedronGeometry;\n\texports.OneFactor = OneFactor;\n\texports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;\n\texports.OneMinusDstColorFactor = OneMinusDstColorFactor;\n\texports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;\n\texports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;\n\texports.OrthographicCamera = OrthographicCamera;\n\texports.PCFShadowMap = PCFShadowMap;\n\texports.PCFSoftShadowMap = PCFSoftShadowMap;\n\texports.ParametricBufferGeometry = ParametricBufferGeometry;\n\texports.ParametricGeometry = ParametricGeometry;\n\texports.Particle = Particle;\n\texports.ParticleBasicMaterial = ParticleBasicMaterial;\n\texports.ParticleSystem = ParticleSystem;\n\texports.ParticleSystemMaterial = ParticleSystemMaterial;\n\texports.Path = Path;\n\texports.PerspectiveCamera = PerspectiveCamera;\n\texports.Plane = Plane;\n\texports.PlaneBufferGeometry = PlaneBufferGeometry;\n\texports.PlaneGeometry = PlaneGeometry;\n\texports.PlaneHelper = PlaneHelper;\n\texports.PointCloud = PointCloud;\n\texports.PointCloudMaterial = PointCloudMaterial;\n\texports.PointLight = PointLight;\n\texports.PointLightHelper = PointLightHelper;\n\texports.Points = Points;\n\texports.PointsMaterial = PointsMaterial;\n\texports.PolarGridHelper = PolarGridHelper;\n\texports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;\n\texports.PolyhedronGeometry = PolyhedronGeometry;\n\texports.PositionalAudio = PositionalAudio;\n\texports.PositionalAudioHelper = PositionalAudioHelper;\n\texports.PropertyBinding = PropertyBinding;\n\texports.PropertyMixer = PropertyMixer;\n\texports.QuadraticBezierCurve = QuadraticBezierCurve;\n\texports.QuadraticBezierCurve3 = QuadraticBezierCurve3;\n\texports.Quaternion = Quaternion;\n\texports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;\n\texports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;\n\texports.REVISION = REVISION;\n\texports.RGBADepthPacking = RGBADepthPacking;\n\texports.RGBAFormat = RGBAFormat;\n\texports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;\n\texports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;\n\texports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;\n\texports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;\n\texports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;\n\texports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;\n\texports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;\n\texports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;\n\texports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;\n\texports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;\n\texports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;\n\texports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;\n\texports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;\n\texports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;\n\texports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;\n\texports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;\n\texports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;\n\texports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;\n\texports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;\n\texports.RGBDEncoding = RGBDEncoding;\n\texports.RGBEEncoding = RGBEEncoding;\n\texports.RGBEFormat = RGBEFormat;\n\texports.RGBFormat = RGBFormat;\n\texports.RGBM16Encoding = RGBM16Encoding;\n\texports.RGBM7Encoding = RGBM7Encoding;\n\texports.RGB_ETC1_Format = RGB_ETC1_Format;\n\texports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;\n\texports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;\n\texports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;\n\texports.RawShaderMaterial = RawShaderMaterial;\n\texports.Ray = Ray;\n\texports.Raycaster = Raycaster;\n\texports.RectAreaLight = RectAreaLight;\n\texports.RectAreaLightHelper = RectAreaLightHelper;\n\texports.RedFormat = RedFormat;\n\texports.ReinhardToneMapping = ReinhardToneMapping;\n\texports.RepeatWrapping = RepeatWrapping;\n\texports.ReplaceStencilOp = ReplaceStencilOp;\n\texports.ReverseSubtractEquation = ReverseSubtractEquation;\n\texports.RingBufferGeometry = RingBufferGeometry;\n\texports.RingGeometry = RingGeometry;\n\texports.Scene = Scene;\n\texports.SceneUtils = SceneUtils;\n\texports.ShaderChunk = ShaderChunk;\n\texports.ShaderLib = ShaderLib;\n\texports.ShaderMaterial = ShaderMaterial;\n\texports.ShadowMaterial = ShadowMaterial;\n\texports.Shape = Shape;\n\texports.ShapeBufferGeometry = ShapeBufferGeometry;\n\texports.ShapeGeometry = ShapeGeometry;\n\texports.ShapePath = ShapePath;\n\texports.ShapeUtils = ShapeUtils;\n\texports.ShortType = ShortType;\n\texports.Skeleton = Skeleton;\n\texports.SkeletonHelper = SkeletonHelper;\n\texports.SkinnedMesh = SkinnedMesh;\n\texports.SmoothShading = SmoothShading;\n\texports.Sphere = Sphere;\n\texports.SphereBufferGeometry = SphereBufferGeometry;\n\texports.SphereGeometry = SphereGeometry;\n\texports.Spherical = Spherical;\n\texports.SphericalHarmonics3 = SphericalHarmonics3;\n\texports.SphericalReflectionMapping = SphericalReflectionMapping;\n\texports.Spline = Spline;\n\texports.SplineCurve = SplineCurve;\n\texports.SplineCurve3 = SplineCurve3;\n\texports.SpotLight = SpotLight;\n\texports.SpotLightHelper = SpotLightHelper;\n\texports.SpotLightShadow = SpotLightShadow;\n\texports.Sprite = Sprite;\n\texports.SpriteMaterial = SpriteMaterial;\n\texports.SrcAlphaFactor = SrcAlphaFactor;\n\texports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;\n\texports.SrcColorFactor = SrcColorFactor;\n\texports.StaticCopyUsage = StaticCopyUsage;\n\texports.StaticDrawUsage = StaticDrawUsage;\n\texports.StaticReadUsage = StaticReadUsage;\n\texports.StereoCamera = StereoCamera;\n\texports.StreamCopyUsage = StreamCopyUsage;\n\texports.StreamDrawUsage = StreamDrawUsage;\n\texports.StreamReadUsage = StreamReadUsage;\n\texports.StringKeyframeTrack = StringKeyframeTrack;\n\texports.SubtractEquation = SubtractEquation;\n\texports.SubtractiveBlending = SubtractiveBlending;\n\texports.TOUCH = TOUCH;\n\texports.TangentSpaceNormalMap = TangentSpaceNormalMap;\n\texports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;\n\texports.TetrahedronGeometry = TetrahedronGeometry;\n\texports.TextBufferGeometry = TextBufferGeometry;\n\texports.TextGeometry = TextGeometry;\n\texports.Texture = Texture;\n\texports.TextureLoader = TextureLoader;\n\texports.TorusBufferGeometry = TorusBufferGeometry;\n\texports.TorusGeometry = TorusGeometry;\n\texports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;\n\texports.TorusKnotGeometry = TorusKnotGeometry;\n\texports.Triangle = Triangle;\n\texports.TriangleFanDrawMode = TriangleFanDrawMode;\n\texports.TriangleStripDrawMode = TriangleStripDrawMode;\n\texports.TrianglesDrawMode = TrianglesDrawMode;\n\texports.TubeBufferGeometry = TubeBufferGeometry;\n\texports.TubeGeometry = TubeGeometry;\n\texports.UVMapping = UVMapping;\n\texports.Uint16Attribute = Uint16Attribute;\n\texports.Uint16BufferAttribute = Uint16BufferAttribute;\n\texports.Uint32Attribute = Uint32Attribute;\n\texports.Uint32BufferAttribute = Uint32BufferAttribute;\n\texports.Uint8Attribute = Uint8Attribute;\n\texports.Uint8BufferAttribute = Uint8BufferAttribute;\n\texports.Uint8ClampedAttribute = Uint8ClampedAttribute;\n\texports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;\n\texports.Uncharted2ToneMapping = Uncharted2ToneMapping;\n\texports.Uniform = Uniform;\n\texports.UniformsLib = UniformsLib;\n\texports.UniformsUtils = UniformsUtils;\n\texports.UnsignedByteType = UnsignedByteType;\n\texports.UnsignedInt248Type = UnsignedInt248Type;\n\texports.UnsignedIntType = UnsignedIntType;\n\texports.UnsignedShort4444Type = UnsignedShort4444Type;\n\texports.UnsignedShort5551Type = UnsignedShort5551Type;\n\texports.UnsignedShort565Type = UnsignedShort565Type;\n\texports.UnsignedShortType = UnsignedShortType;\n\texports.VSMShadowMap = VSMShadowMap;\n\texports.Vector2 = Vector2;\n\texports.Vector3 = Vector3;\n\texports.Vector4 = Vector4;\n\texports.VectorKeyframeTrack = VectorKeyframeTrack;\n\texports.Vertex = Vertex;\n\texports.VertexColors = VertexColors;\n\texports.VertexNormalsHelper = VertexNormalsHelper;\n\texports.VertexTangentsHelper = VertexTangentsHelper;\n\texports.VideoTexture = VideoTexture;\n\texports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget;\n\texports.WebGLRenderTarget = WebGLRenderTarget;\n\texports.WebGLRenderTargetCube = WebGLRenderTargetCube;\n\texports.WebGLRenderer = WebGLRenderer;\n\texports.WebGLUtils = WebGLUtils;\n\texports.WireframeGeometry = WireframeGeometry;\n\texports.WireframeHelper = WireframeHelper;\n\texports.WrapAroundEnding = WrapAroundEnding;\n\texports.XHRLoader = XHRLoader;\n\texports.ZeroCurvatureEnding = ZeroCurvatureEnding;\n\texports.ZeroFactor = ZeroFactor;\n\texports.ZeroSlopeEnding = ZeroSlopeEnding;\n\texports.ZeroStencilOp = ZeroStencilOp;\n\texports.sRGBEncoding = sRGBEncoding;\n\n\tObject.defineProperty(exports, '__esModule', { value: true });\n\n}));\n", + "(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n\ttypeof define === 'function' && define.amd ? define(['exports'], factory) :\n\t(global = global || self, factory(global.THREE = {}));\n}(this, (function (exports) { 'use strict';\n\n\t// Polyfills\r\n\r\n\tif ( Number.EPSILON === undefined ) {\r\n\r\n\t\tNumber.EPSILON = Math.pow( 2, - 52 );\r\n\r\n\t}\r\n\r\n\tif ( Number.isInteger === undefined ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger\r\n\r\n\t\tNumber.isInteger = function ( value ) {\r\n\r\n\t\t\treturn typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tif ( Math.sign === undefined ) {\r\n\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign\r\n\r\n\t\tMath.sign = function ( x ) {\r\n\r\n\t\t\treturn ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tif ( 'name' in Function.prototype === false ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name\r\n\r\n\t\tObject.defineProperty( Function.prototype, 'name', {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.toString().match( /^\\s*function\\s*([^\\(\\s]*)/ )[ 1 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\tif ( Object.assign === undefined ) {\r\n\r\n\t\t// Missing in IE\r\n\t\t// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\r\n\r\n\t\tObject.assign = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined || target === null ) {\r\n\r\n\t\t\t\tthrow new TypeError( 'Cannot convert undefined or null to object' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar output = Object( target );\r\n\r\n\t\t\tfor ( var index = 1; index < arguments.length; index ++ ) {\r\n\r\n\t\t\t\tvar source = arguments[ index ];\r\n\r\n\t\t\t\tif ( source !== undefined && source !== null ) {\r\n\r\n\t\t\t\t\tfor ( var nextKey in source ) {\r\n\r\n\t\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) {\r\n\r\n\t\t\t\t\t\t\toutput[ nextKey ] = source[ nextKey ];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t};\r\n\r\n\t}\n\n\tvar REVISION = '111dev';\r\n\tvar MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };\r\n\tvar TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };\r\n\tvar CullFaceNone = 0;\r\n\tvar CullFaceBack = 1;\r\n\tvar CullFaceFront = 2;\r\n\tvar CullFaceFrontBack = 3;\r\n\tvar FrontFaceDirectionCW = 0;\r\n\tvar FrontFaceDirectionCCW = 1;\r\n\tvar BasicShadowMap = 0;\r\n\tvar PCFShadowMap = 1;\r\n\tvar PCFSoftShadowMap = 2;\r\n\tvar VSMShadowMap = 3;\r\n\tvar FrontSide = 0;\r\n\tvar BackSide = 1;\r\n\tvar DoubleSide = 2;\r\n\tvar FlatShading = 1;\r\n\tvar SmoothShading = 2;\r\n\tvar NoColors = 0;\r\n\tvar FaceColors = 1;\r\n\tvar VertexColors = 2;\r\n\tvar NoBlending = 0;\r\n\tvar NormalBlending = 1;\r\n\tvar AdditiveBlending = 2;\r\n\tvar SubtractiveBlending = 3;\r\n\tvar MultiplyBlending = 4;\r\n\tvar CustomBlending = 5;\r\n\tvar AddEquation = 100;\r\n\tvar SubtractEquation = 101;\r\n\tvar ReverseSubtractEquation = 102;\r\n\tvar MinEquation = 103;\r\n\tvar MaxEquation = 104;\r\n\tvar ZeroFactor = 200;\r\n\tvar OneFactor = 201;\r\n\tvar SrcColorFactor = 202;\r\n\tvar OneMinusSrcColorFactor = 203;\r\n\tvar SrcAlphaFactor = 204;\r\n\tvar OneMinusSrcAlphaFactor = 205;\r\n\tvar DstAlphaFactor = 206;\r\n\tvar OneMinusDstAlphaFactor = 207;\r\n\tvar DstColorFactor = 208;\r\n\tvar OneMinusDstColorFactor = 209;\r\n\tvar SrcAlphaSaturateFactor = 210;\r\n\tvar NeverDepth = 0;\r\n\tvar AlwaysDepth = 1;\r\n\tvar LessDepth = 2;\r\n\tvar LessEqualDepth = 3;\r\n\tvar EqualDepth = 4;\r\n\tvar GreaterEqualDepth = 5;\r\n\tvar GreaterDepth = 6;\r\n\tvar NotEqualDepth = 7;\r\n\tvar MultiplyOperation = 0;\r\n\tvar MixOperation = 1;\r\n\tvar AddOperation = 2;\r\n\tvar NoToneMapping = 0;\r\n\tvar LinearToneMapping = 1;\r\n\tvar ReinhardToneMapping = 2;\r\n\tvar Uncharted2ToneMapping = 3;\r\n\tvar CineonToneMapping = 4;\r\n\tvar ACESFilmicToneMapping = 5;\r\n\r\n\tvar UVMapping = 300;\r\n\tvar CubeReflectionMapping = 301;\r\n\tvar CubeRefractionMapping = 302;\r\n\tvar EquirectangularReflectionMapping = 303;\r\n\tvar EquirectangularRefractionMapping = 304;\r\n\tvar SphericalReflectionMapping = 305;\r\n\tvar CubeUVReflectionMapping = 306;\r\n\tvar CubeUVRefractionMapping = 307;\r\n\tvar RepeatWrapping = 1000;\r\n\tvar ClampToEdgeWrapping = 1001;\r\n\tvar MirroredRepeatWrapping = 1002;\r\n\tvar NearestFilter = 1003;\r\n\tvar NearestMipmapNearestFilter = 1004;\r\n\tvar NearestMipMapNearestFilter = 1004;\r\n\tvar NearestMipmapLinearFilter = 1005;\r\n\tvar NearestMipMapLinearFilter = 1005;\r\n\tvar LinearFilter = 1006;\r\n\tvar LinearMipmapNearestFilter = 1007;\r\n\tvar LinearMipMapNearestFilter = 1007;\r\n\tvar LinearMipmapLinearFilter = 1008;\r\n\tvar LinearMipMapLinearFilter = 1008;\r\n\tvar UnsignedByteType = 1009;\r\n\tvar ByteType = 1010;\r\n\tvar ShortType = 1011;\r\n\tvar UnsignedShortType = 1012;\r\n\tvar IntType = 1013;\r\n\tvar UnsignedIntType = 1014;\r\n\tvar FloatType = 1015;\r\n\tvar HalfFloatType = 1016;\r\n\tvar UnsignedShort4444Type = 1017;\r\n\tvar UnsignedShort5551Type = 1018;\r\n\tvar UnsignedShort565Type = 1019;\r\n\tvar UnsignedInt248Type = 1020;\r\n\tvar AlphaFormat = 1021;\r\n\tvar RGBFormat = 1022;\r\n\tvar RGBAFormat = 1023;\r\n\tvar LuminanceFormat = 1024;\r\n\tvar LuminanceAlphaFormat = 1025;\r\n\tvar RGBEFormat = RGBAFormat;\r\n\tvar DepthFormat = 1026;\r\n\tvar DepthStencilFormat = 1027;\r\n\tvar RedFormat = 1028;\r\n\tvar RGB_S3TC_DXT1_Format = 33776;\r\n\tvar RGBA_S3TC_DXT1_Format = 33777;\r\n\tvar RGBA_S3TC_DXT3_Format = 33778;\r\n\tvar RGBA_S3TC_DXT5_Format = 33779;\r\n\tvar RGB_PVRTC_4BPPV1_Format = 35840;\r\n\tvar RGB_PVRTC_2BPPV1_Format = 35841;\r\n\tvar RGBA_PVRTC_4BPPV1_Format = 35842;\r\n\tvar RGBA_PVRTC_2BPPV1_Format = 35843;\r\n\tvar RGB_ETC1_Format = 36196;\r\n\tvar RGBA_ASTC_4x4_Format = 37808;\r\n\tvar RGBA_ASTC_5x4_Format = 37809;\r\n\tvar RGBA_ASTC_5x5_Format = 37810;\r\n\tvar RGBA_ASTC_6x5_Format = 37811;\r\n\tvar RGBA_ASTC_6x6_Format = 37812;\r\n\tvar RGBA_ASTC_8x5_Format = 37813;\r\n\tvar RGBA_ASTC_8x6_Format = 37814;\r\n\tvar RGBA_ASTC_8x8_Format = 37815;\r\n\tvar RGBA_ASTC_10x5_Format = 37816;\r\n\tvar RGBA_ASTC_10x6_Format = 37817;\r\n\tvar RGBA_ASTC_10x8_Format = 37818;\r\n\tvar RGBA_ASTC_10x10_Format = 37819;\r\n\tvar RGBA_ASTC_12x10_Format = 37820;\r\n\tvar RGBA_ASTC_12x12_Format = 37821;\r\n\tvar LoopOnce = 2200;\r\n\tvar LoopRepeat = 2201;\r\n\tvar LoopPingPong = 2202;\r\n\tvar InterpolateDiscrete = 2300;\r\n\tvar InterpolateLinear = 2301;\r\n\tvar InterpolateSmooth = 2302;\r\n\tvar ZeroCurvatureEnding = 2400;\r\n\tvar ZeroSlopeEnding = 2401;\r\n\tvar WrapAroundEnding = 2402;\r\n\tvar TrianglesDrawMode = 0;\r\n\tvar TriangleStripDrawMode = 1;\r\n\tvar TriangleFanDrawMode = 2;\r\n\tvar LinearEncoding = 3000;\r\n\tvar sRGBEncoding = 3001;\r\n\tvar GammaEncoding = 3007;\r\n\tvar RGBEEncoding = 3002;\r\n\tvar LogLuvEncoding = 3003;\r\n\tvar RGBM7Encoding = 3004;\r\n\tvar RGBM16Encoding = 3005;\r\n\tvar RGBDEncoding = 3006;\r\n\tvar BasicDepthPacking = 3200;\r\n\tvar RGBADepthPacking = 3201;\r\n\tvar TangentSpaceNormalMap = 0;\r\n\tvar ObjectSpaceNormalMap = 1;\r\n\r\n\tvar ZeroStencilOp = 0;\r\n\tvar KeepStencilOp = 7680;\r\n\tvar ReplaceStencilOp = 7681;\r\n\tvar IncrementStencilOp = 7682;\r\n\tvar DecrementStencilOp = 7683;\r\n\tvar IncrementWrapStencilOp = 34055;\r\n\tvar DecrementWrapStencilOp = 34056;\r\n\tvar InvertStencilOp = 5386;\r\n\r\n\tvar NeverStencilFunc = 512;\r\n\tvar LessStencilFunc = 513;\r\n\tvar EqualStencilFunc = 514;\r\n\tvar LessEqualStencilFunc = 515;\r\n\tvar GreaterStencilFunc = 516;\r\n\tvar NotEqualStencilFunc = 517;\r\n\tvar GreaterEqualStencilFunc = 518;\r\n\tvar AlwaysStencilFunc = 519;\r\n\r\n\tvar StaticDrawUsage = 35044;\r\n\tvar DynamicDrawUsage = 35048;\r\n\tvar StreamDrawUsage = 35040;\r\n\tvar StaticReadUsage = 35045;\r\n\tvar DynamicReadUsage = 35049;\r\n\tvar StreamReadUsage = 35041;\r\n\tvar StaticCopyUsage = 35046;\r\n\tvar DynamicCopyUsage = 35050;\r\n\tvar StreamCopyUsage = 35042;\n\n\t/**\r\n\t * https://github.com/mrdoob/eventdispatcher.js/\r\n\t */\r\n\r\n\tfunction EventDispatcher() {}\r\n\r\n\tObject.assign( EventDispatcher.prototype, {\r\n\r\n\t\taddEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { this._listeners = {}; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\r\n\t\t\tif ( listeners[ type ] === undefined ) {\r\n\r\n\t\t\t\tlisteners[ type ] = [];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( listeners[ type ].indexOf( listener ) === - 1 ) {\r\n\r\n\t\t\t\tlisteners[ type ].push( listener );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\thasEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return false; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\r\n\t\t\treturn listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;\r\n\r\n\t\t},\r\n\r\n\t\tremoveEventListener: function ( type, listener ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\t\t\tvar listenerArray = listeners[ type ];\r\n\r\n\t\t\tif ( listenerArray !== undefined ) {\r\n\r\n\t\t\t\tvar index = listenerArray.indexOf( listener );\r\n\r\n\t\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\t\tlistenerArray.splice( index, 1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tdispatchEvent: function ( event ) {\r\n\r\n\t\t\tif ( this._listeners === undefined ) { return; }\r\n\r\n\t\t\tvar listeners = this._listeners;\r\n\t\t\tvar listenerArray = listeners[ event.type ];\r\n\r\n\t\t\tif ( listenerArray !== undefined ) {\r\n\r\n\t\t\t\tevent.target = this;\r\n\r\n\t\t\t\tvar array = listenerArray.slice( 0 );\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tarray[ i ].call( this, event );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _lut = [];\r\n\r\n\tfor ( var i = 0; i < 256; i ++ ) {\r\n\r\n\t\t_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );\r\n\r\n\t}\r\n\r\n\tvar _Math = {\r\n\r\n\t\tDEG2RAD: Math.PI / 180,\r\n\t\tRAD2DEG: 180 / Math.PI,\r\n\r\n\t\tgenerateUUID: function () {\r\n\r\n\t\t\t// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136\r\n\r\n\t\t\tvar d0 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d1 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d2 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar d3 = Math.random() * 0xffffffff | 0;\r\n\t\t\tvar uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +\r\n\t\t\t\t_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +\r\n\t\t\t\t_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +\r\n\t\t\t\t_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];\r\n\r\n\t\t\t// .toUpperCase() here flattens concatenated strings to save heap memory space.\r\n\t\t\treturn uuid.toUpperCase();\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( value, min, max ) {\r\n\r\n\t\t\treturn Math.max( min, Math.min( max, value ) );\r\n\r\n\t\t},\r\n\r\n\t\t// compute euclidian modulo of m % n\r\n\t\t// https://en.wikipedia.org/wiki/Modulo_operation\r\n\r\n\t\teuclideanModulo: function ( n, m ) {\r\n\r\n\t\t\treturn ( ( n % m ) + m ) % m;\r\n\r\n\t\t},\r\n\r\n\t\t// Linear mapping from range to range \r\n\r\n\t\tmapLinear: function ( x, a1, a2, b1, b2 ) {\r\n\r\n\t\t\treturn b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );\r\n\r\n\t\t},\r\n\r\n\t\t// https://en.wikipedia.org/wiki/Linear_interpolation\r\n\r\n\t\tlerp: function ( x, y, t ) {\r\n\r\n\t\t\treturn ( 1 - t ) * x + t * y;\r\n\r\n\t\t},\r\n\r\n\t\t// http://en.wikipedia.org/wiki/Smoothstep\r\n\r\n\t\tsmoothstep: function ( x, min, max ) {\r\n\r\n\t\t\tif ( x <= min ) { return 0; }\r\n\t\t\tif ( x >= max ) { return 1; }\r\n\r\n\t\t\tx = ( x - min ) / ( max - min );\r\n\r\n\t\t\treturn x * x * ( 3 - 2 * x );\r\n\r\n\t\t},\r\n\r\n\t\tsmootherstep: function ( x, min, max ) {\r\n\r\n\t\t\tif ( x <= min ) { return 0; }\r\n\t\t\tif ( x >= max ) { return 1; }\r\n\r\n\t\t\tx = ( x - min ) / ( max - min );\r\n\r\n\t\t\treturn x * x * x * ( x * ( x * 6 - 15 ) + 10 );\r\n\r\n\t\t},\r\n\r\n\t\t// Random integer from interval\r\n\r\n\t\trandInt: function ( low, high ) {\r\n\r\n\t\t\treturn low + Math.floor( Math.random() * ( high - low + 1 ) );\r\n\r\n\t\t},\r\n\r\n\t\t// Random float from interval\r\n\r\n\t\trandFloat: function ( low, high ) {\r\n\r\n\t\t\treturn low + Math.random() * ( high - low );\r\n\r\n\t\t},\r\n\r\n\t\t// Random float from <-range/2, range/2> interval\r\n\r\n\t\trandFloatSpread: function ( range ) {\r\n\r\n\t\t\treturn range * ( 0.5 - Math.random() );\r\n\r\n\t\t},\r\n\r\n\t\tdegToRad: function ( degrees ) {\r\n\r\n\t\t\treturn degrees * _Math.DEG2RAD;\r\n\r\n\t\t},\r\n\r\n\t\tradToDeg: function ( radians ) {\r\n\r\n\t\t\treturn radians * _Math.RAD2DEG;\r\n\r\n\t\t},\r\n\r\n\t\tisPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn ( value & ( value - 1 ) ) === 0 && value !== 0;\r\n\r\n\t\t},\r\n\r\n\t\tceilPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloorPowerOfTwo: function ( value ) {\r\n\r\n\t\t\treturn Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t */\r\n\r\n\tfunction Vector2( x, y ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( Vector2.prototype, {\r\n\r\n\t\t\"width\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.x = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t\"height\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.y = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector2.prototype, {\r\n\r\n\t\tisVector2: true,\r\n\r\n\t\tset: function ( x, y ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( v ) {\r\n\r\n\t\t\tthis.x *= v.x;\r\n\t\t\tthis.y *= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivide: function ( v ) {\r\n\r\n\t\t\tthis.x /= v.x;\r\n\t\t\tthis.y /= v.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y;\r\n\r\n\t\t},\r\n\r\n\t\tcross: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.y - this.y * v.x;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tangle: function () {\r\n\r\n\t\t\t// computes the angle in radians with respect to the positive x-axis\r\n\r\n\t\t\tvar angle = Math.atan2( this.y, this.x );\r\n\r\n\t\t\tif ( angle < 0 ) { angle += 2 * Math.PI; }\r\n\r\n\t\t\treturn angle;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceToSquared( v ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSquared: function ( v ) {\r\n\r\n\t\t\tvar dx = this.x - v.x, dy = this.y - v.y;\r\n\t\t\treturn dx * dx + dy * dy;\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanDistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateAround: function ( center, angle ) {\r\n\r\n\t\t\tvar c = Math.cos( angle ), s = Math.sin( angle );\r\n\r\n\t\t\tvar x = this.x - center.x;\r\n\t\t\tvar y = this.y - center.y;\r\n\r\n\t\t\tthis.x = x * c - y * s + center.x;\r\n\t\t\tthis.y = x * s + y * c + center.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tfunction Quaternion( x, y, z, w ) {\r\n\r\n\t\tthis._x = x || 0;\r\n\t\tthis._y = y || 0;\r\n\t\tthis._z = z || 0;\r\n\t\tthis._w = ( w !== undefined ) ? w : 1;\r\n\r\n\t}\r\n\r\n\tObject.assign( Quaternion, {\r\n\r\n\t\tslerp: function ( qa, qb, qm, t ) {\r\n\r\n\t\t\treturn qm.copy( qa ).slerp( qb, t );\r\n\r\n\t\t},\r\n\r\n\t\tslerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {\r\n\r\n\t\t\t// fuzz-free, array-based Quaternion SLERP operation\r\n\r\n\t\t\tvar x0 = src0[ srcOffset0 + 0 ],\r\n\t\t\t\ty0 = src0[ srcOffset0 + 1 ],\r\n\t\t\t\tz0 = src0[ srcOffset0 + 2 ],\r\n\t\t\t\tw0 = src0[ srcOffset0 + 3 ],\r\n\r\n\t\t\t\tx1 = src1[ srcOffset1 + 0 ],\r\n\t\t\t\ty1 = src1[ srcOffset1 + 1 ],\r\n\t\t\t\tz1 = src1[ srcOffset1 + 2 ],\r\n\t\t\t\tw1 = src1[ srcOffset1 + 3 ];\r\n\r\n\t\t\tif ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {\r\n\r\n\t\t\t\tvar s = 1 - t,\r\n\r\n\t\t\t\t\tcos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,\r\n\r\n\t\t\t\t\tdir = ( cos >= 0 ? 1 : - 1 ),\r\n\t\t\t\t\tsqrSin = 1 - cos * cos;\r\n\r\n\t\t\t\t// Skip the Slerp for tiny steps to avoid numeric problems:\r\n\t\t\t\tif ( sqrSin > Number.EPSILON ) {\r\n\r\n\t\t\t\t\tvar sin = Math.sqrt( sqrSin ),\r\n\t\t\t\t\t\tlen = Math.atan2( sin, cos * dir );\r\n\r\n\t\t\t\t\ts = Math.sin( s * len ) / sin;\r\n\t\t\t\t\tt = Math.sin( t * len ) / sin;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar tDir = t * dir;\r\n\r\n\t\t\t\tx0 = x0 * s + x1 * tDir;\r\n\t\t\t\ty0 = y0 * s + y1 * tDir;\r\n\t\t\t\tz0 = z0 * s + z1 * tDir;\r\n\t\t\t\tw0 = w0 * s + w1 * tDir;\r\n\r\n\t\t\t\t// Normalize in case we just did a lerp:\r\n\t\t\t\tif ( s === 1 - t ) {\r\n\r\n\t\t\t\t\tvar f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );\r\n\r\n\t\t\t\t\tx0 *= f;\r\n\t\t\t\t\ty0 *= f;\r\n\t\t\t\t\tz0 *= f;\r\n\t\t\t\t\tw0 *= f;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdst[ dstOffset ] = x0;\r\n\t\t\tdst[ dstOffset + 1 ] = y0;\r\n\t\t\tdst[ dstOffset + 2 ] = z0;\r\n\t\t\tdst[ dstOffset + 3 ] = w0;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Quaternion.prototype, {\r\n\r\n\t\tx: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._x = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ty: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._y = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tz: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._z = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tw: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._w;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._w = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Quaternion.prototype, {\r\n\r\n\t\tisQuaternion: true,\r\n\r\n\t\tset: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis._x = x;\r\n\t\t\tthis._y = y;\r\n\t\t\tthis._z = z;\r\n\t\t\tthis._w = w;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this._x, this._y, this._z, this._w );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( quaternion ) {\r\n\r\n\t\t\tthis._x = quaternion.x;\r\n\t\t\tthis._y = quaternion.y;\r\n\t\t\tthis._z = quaternion.z;\r\n\t\t\tthis._w = quaternion.w;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromEuler: function ( euler, update ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tthrow new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar x = euler._x, y = euler._y, z = euler._z, order = euler.order;\r\n\r\n\t\t\t// http://www.mathworks.com/matlabcentral/fileexchange/\r\n\t\t\t// \t20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\r\n\t\t\t//\tcontent/SpinCalc.m\r\n\r\n\t\t\tvar cos = Math.cos;\r\n\t\t\tvar sin = Math.sin;\r\n\r\n\t\t\tvar c1 = cos( x / 2 );\r\n\t\t\tvar c2 = cos( y / 2 );\r\n\t\t\tvar c3 = cos( z / 2 );\r\n\r\n\t\t\tvar s1 = sin( x / 2 );\r\n\t\t\tvar s2 = sin( y / 2 );\r\n\t\t\tvar s3 = sin( z / 2 );\r\n\r\n\t\t\tif ( order === 'XYZ' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'YXZ' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'ZXY' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'ZYX' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'YZX' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\r\n\r\n\t\t\t} else if ( order === 'XZY' ) {\r\n\r\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\r\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\r\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\r\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( update !== false ) { this._onChangeCallback(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\r\n\r\n\t\t\t// assumes axis is normalized\r\n\r\n\t\t\tvar halfAngle = angle / 2, s = Math.sin( halfAngle );\r\n\r\n\t\t\tthis._x = axis.x * s;\r\n\t\t\tthis._y = axis.y * s;\r\n\t\t\tthis._z = axis.z * s;\r\n\t\t\tthis._w = Math.cos( halfAngle );\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromRotationMatrix: function ( m ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar te = m.elements,\r\n\r\n\t\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\r\n\t\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\r\n\t\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],\r\n\r\n\t\t\t\ttrace = m11 + m22 + m33,\r\n\t\t\t\ts;\r\n\r\n\t\t\tif ( trace > 0 ) {\r\n\r\n\t\t\t\ts = 0.5 / Math.sqrt( trace + 1.0 );\r\n\r\n\t\t\t\tthis._w = 0.25 / s;\r\n\t\t\t\tthis._x = ( m32 - m23 ) * s;\r\n\t\t\t\tthis._y = ( m13 - m31 ) * s;\r\n\t\t\t\tthis._z = ( m21 - m12 ) * s;\r\n\r\n\t\t\t} else if ( m11 > m22 && m11 > m33 ) {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );\r\n\r\n\t\t\t\tthis._w = ( m32 - m23 ) / s;\r\n\t\t\t\tthis._x = 0.25 * s;\r\n\t\t\t\tthis._y = ( m12 + m21 ) / s;\r\n\t\t\t\tthis._z = ( m13 + m31 ) / s;\r\n\r\n\t\t\t} else if ( m22 > m33 ) {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );\r\n\r\n\t\t\t\tthis._w = ( m13 - m31 ) / s;\r\n\t\t\t\tthis._x = ( m12 + m21 ) / s;\r\n\t\t\t\tthis._y = 0.25 * s;\r\n\t\t\t\tthis._z = ( m23 + m32 ) / s;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ts = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );\r\n\r\n\t\t\t\tthis._w = ( m21 - m12 ) / s;\r\n\t\t\t\tthis._x = ( m13 + m31 ) / s;\r\n\t\t\t\tthis._y = ( m23 + m32 ) / s;\r\n\t\t\t\tthis._z = 0.25 * s;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromUnitVectors: function ( vFrom, vTo ) {\r\n\r\n\t\t\t// assumes direction vectors vFrom and vTo are normalized\r\n\r\n\t\t\tvar EPS = 0.000001;\r\n\r\n\t\t\tvar r = vFrom.dot( vTo ) + 1;\r\n\r\n\t\t\tif ( r < EPS ) {\r\n\r\n\t\t\t\tr = 0;\r\n\r\n\t\t\t\tif ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {\r\n\r\n\t\t\t\t\tthis._x = - vFrom.y;\r\n\t\t\t\t\tthis._y = vFrom.x;\r\n\t\t\t\t\tthis._z = 0;\r\n\t\t\t\t\tthis._w = r;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._y = - vFrom.z;\r\n\t\t\t\t\tthis._z = vFrom.y;\r\n\t\t\t\t\tthis._w = r;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3\r\n\r\n\t\t\t\tthis._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\r\n\t\t\t\tthis._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\r\n\t\t\t\tthis._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\r\n\t\t\t\tthis._w = r;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tangleTo: function ( q ) {\r\n\r\n\t\t\treturn 2 * Math.acos( Math.abs( _Math.clamp( this.dot( q ), - 1, 1 ) ) );\r\n\r\n\t\t},\r\n\r\n\t\trotateTowards: function ( q, step ) {\r\n\r\n\t\t\tvar angle = this.angleTo( q );\r\n\r\n\t\t\tif ( angle === 0 ) { return this; }\r\n\r\n\t\t\tvar t = Math.min( 1, step / angle );\r\n\r\n\t\t\tthis.slerp( q, t );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tinverse: function () {\r\n\r\n\t\t\t// quaternion is assumed to have unit length\r\n\r\n\t\t\treturn this.conjugate();\r\n\r\n\t\t},\r\n\r\n\t\tconjugate: function () {\r\n\r\n\t\t\tthis._x *= - 1;\r\n\t\t\tthis._y *= - 1;\r\n\t\t\tthis._z *= - 1;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\tvar l = this.length();\r\n\r\n\t\t\tif ( l === 0 ) {\r\n\r\n\t\t\t\tthis._x = 0;\r\n\t\t\t\tthis._y = 0;\r\n\t\t\t\tthis._z = 0;\r\n\t\t\t\tthis._w = 1;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tl = 1 / l;\r\n\r\n\t\t\t\tthis._x = this._x * l;\r\n\t\t\t\tthis._y = this._y * l;\r\n\t\t\t\tthis._z = this._z * l;\r\n\t\t\t\tthis._w = this._w * l;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( q, p ) {\r\n\r\n\t\t\tif ( p !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyQuaternions( q, p );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.multiplyQuaternions( this, q );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( q ) {\r\n\r\n\t\t\treturn this.multiplyQuaternions( q, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyQuaternions: function ( a, b ) {\r\n\r\n\t\t\t// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm\r\n\r\n\t\t\tvar qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\r\n\t\t\tvar qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\r\n\r\n\t\t\tthis._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\r\n\t\t\tthis._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\r\n\t\t\tthis._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\r\n\t\t\tthis._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tslerp: function ( qb, t ) {\r\n\r\n\t\t\tif ( t === 0 ) { return this; }\r\n\t\t\tif ( t === 1 ) { return this.copy( qb ); }\r\n\r\n\t\t\tvar x = this._x, y = this._y, z = this._z, w = this._w;\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/\r\n\r\n\t\t\tvar cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;\r\n\r\n\t\t\tif ( cosHalfTheta < 0 ) {\r\n\r\n\t\t\t\tthis._w = - qb._w;\r\n\t\t\t\tthis._x = - qb._x;\r\n\t\t\t\tthis._y = - qb._y;\r\n\t\t\t\tthis._z = - qb._z;\r\n\r\n\t\t\t\tcosHalfTheta = - cosHalfTheta;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.copy( qb );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( cosHalfTheta >= 1.0 ) {\r\n\r\n\t\t\t\tthis._w = w;\r\n\t\t\t\tthis._x = x;\r\n\t\t\t\tthis._y = y;\r\n\t\t\t\tthis._z = z;\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;\r\n\r\n\t\t\tif ( sqrSinHalfTheta <= Number.EPSILON ) {\r\n\r\n\t\t\t\tvar s = 1 - t;\r\n\t\t\t\tthis._w = s * w + t * this._w;\r\n\t\t\t\tthis._x = s * x + t * this._x;\r\n\t\t\t\tthis._y = s * y + t * this._y;\r\n\t\t\t\tthis._z = s * z + t * this._z;\r\n\r\n\t\t\t\tthis.normalize();\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar sinHalfTheta = Math.sqrt( sqrSinHalfTheta );\r\n\t\t\tvar halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );\r\n\t\t\tvar ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,\r\n\t\t\t\tratioB = Math.sin( t * halfTheta ) / sinHalfTheta;\r\n\r\n\t\t\tthis._w = ( w * ratioA + this._w * ratioB );\r\n\t\t\tthis._x = ( x * ratioA + this._x * ratioB );\r\n\t\t\tthis._y = ( y * ratioA + this._y * ratioB );\r\n\t\t\tthis._z = ( z * ratioA + this._z * ratioB );\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( quaternion ) {\r\n\r\n\t\t\treturn ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis._x = array[ offset ];\r\n\t\t\tthis._y = array[ offset + 1 ];\r\n\t\t\tthis._z = array[ offset + 2 ];\r\n\t\t\tthis._w = array[ offset + 3 ];\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this._x;\r\n\t\t\tarray[ offset + 1 ] = this._y;\r\n\t\t\tarray[ offset + 2 ] = this._z;\r\n\t\t\tarray[ offset + 3 ] = this._w;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\t_onChange: function ( callback ) {\r\n\r\n\t\t\tthis._onChangeCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t_onChangeCallback: function () {}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author kile / http://kile.stravaganza.org/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _vector = new Vector3();\r\n\tvar _quaternion = new Quaternion();\r\n\r\n\tfunction Vector3( x, y, z ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\t\tthis.z = z || 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Vector3.prototype, {\r\n\r\n\t\tisVector3: true,\r\n\r\n\t\tset: function ( x, y, z ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\t\t\tthis.z = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( z ) {\r\n\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tcase 2: this.z = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tcase 2: return this.z;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y, this.z );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\t\t\tthis.z = v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\t\t\tthis.z += v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\t\t\tthis.z += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\t\t\tthis.z = a.z + b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\t\t\tthis.z += v.z * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\t\t\tthis.z -= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\t\t\tthis.z -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\t\t\tthis.z = a.z - b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x *= v.x;\r\n\t\t\tthis.y *= v.y;\r\n\t\t\tthis.z *= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\t\t\tthis.z *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x * b.x;\r\n\t\t\tthis.y = a.y * b.y;\r\n\t\t\tthis.z = a.z * b.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyEuler: function ( euler ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.applyQuaternion( _quaternion.setFromEuler( euler ) );\r\n\r\n\t\t},\r\n\r\n\t\tapplyAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\treturn this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyNormalMatrix: function ( m ) {\r\n\r\n\t\t\treturn this.applyMatrix3( m ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tvar w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );\r\n\r\n\t\t\tthis.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;\r\n\t\t\tthis.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;\r\n\t\t\tthis.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyQuaternion: function ( q ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar qx = q.x, qy = q.y, qz = q.z, qw = q.w;\r\n\r\n\t\t\t// calculate quat * vector\r\n\r\n\t\t\tvar ix = qw * x + qy * z - qz * y;\r\n\t\t\tvar iy = qw * y + qz * x - qx * z;\r\n\t\t\tvar iz = qw * z + qx * y - qy * x;\r\n\t\t\tvar iw = - qx * x - qy * y - qz * z;\r\n\r\n\t\t\t// calculate result * inverse quat\r\n\r\n\t\t\tthis.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;\r\n\t\t\tthis.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;\r\n\t\t\tthis.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tproject: function ( camera ) {\r\n\r\n\t\t\treturn this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\tunproject: function ( camera ) {\r\n\r\n\t\t\treturn this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\ttransformDirection: function ( m ) {\r\n\r\n\t\t\t// input: THREE.Matrix4 affine matrix\r\n\t\t\t// vector interpreted as a direction\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;\r\n\r\n\t\t\treturn this.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tdivide: function ( v ) {\r\n\r\n\t\t\tthis.x /= v.x;\r\n\t\t\tthis.y /= v.y;\r\n\t\t\tthis.z /= v.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\t\t\tthis.z = Math.min( this.z, v.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\t\t\tthis.z = Math.max( this.z, v.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\t\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\t\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\t\t\tthis.z = Math.floor( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\t\t\tthis.z = Math.ceil( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\t\t\tthis.z = Math.round( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\t\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\t\t\tthis.z = - this.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\r\n\r\n\t\t},\r\n\r\n\t\t// TODO lengthSquared?\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y + this.z * this.z;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\t\t\tthis.z += ( v.z - this.z ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tcross: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.crossVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.crossVectors( this, v );\r\n\r\n\t\t},\r\n\r\n\t\tcrossVectors: function ( a, b ) {\r\n\r\n\t\t\tvar ax = a.x, ay = a.y, az = a.z;\r\n\t\t\tvar bx = b.x, by = b.y, bz = b.z;\r\n\r\n\t\t\tthis.x = ay * bz - az * by;\r\n\t\t\tthis.y = az * bx - ax * bz;\r\n\t\t\tthis.z = ax * by - ay * bx;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tprojectOnVector: function ( v ) {\r\n\r\n\t\t\t// v cannot be the zero v\r\n\r\n\t\t\tvar scalar = v.dot( this ) / v.lengthSq();\r\n\r\n\t\t\treturn this.copy( v ).multiplyScalar( scalar );\r\n\r\n\t\t},\r\n\r\n\t\tprojectOnPlane: function ( planeNormal ) {\r\n\r\n\t\t\t_vector.copy( this ).projectOnVector( planeNormal );\r\n\r\n\t\t\treturn this.sub( _vector );\r\n\r\n\t\t},\r\n\r\n\t\treflect: function ( normal ) {\r\n\r\n\t\t\t// reflect incident vector off plane orthogonal to normal\r\n\t\t\t// normal is assumed to have unit length\r\n\r\n\t\t\treturn this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tangleTo: function ( v ) {\r\n\r\n\t\t\tvar denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );\r\n\r\n\t\t\tif ( denominator === 0 ) { console.error( 'THREE.Vector3: angleTo() can\\'t handle zero length vectors.' ); }\r\n\r\n\t\t\tvar theta = this.dot( v ) / denominator;\r\n\r\n\t\t\t// clamp, to handle numerical problems\r\n\r\n\t\t\treturn Math.acos( _Math.clamp( theta, - 1, 1 ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceToSquared( v ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSquared: function ( v ) {\r\n\r\n\t\t\tvar dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\r\n\r\n\t\t\treturn dx * dx + dy * dy + dz * dz;\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanDistanceTo: function ( v ) {\r\n\r\n\t\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromSpherical: function ( s ) {\r\n\r\n\t\t\treturn this.setFromSphericalCoords( s.radius, s.phi, s.theta );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromSphericalCoords: function ( radius, phi, theta ) {\r\n\r\n\t\t\tvar sinPhiRadius = Math.sin( phi ) * radius;\r\n\r\n\t\t\tthis.x = sinPhiRadius * Math.sin( theta );\r\n\t\t\tthis.y = Math.cos( phi ) * radius;\r\n\t\t\tthis.z = sinPhiRadius * Math.cos( theta );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCylindrical: function ( c ) {\r\n\r\n\t\t\treturn this.setFromCylindricalCoords( c.radius, c.theta, c.y );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCylindricalCoords: function ( radius, theta, y ) {\r\n\r\n\t\t\tthis.x = radius * Math.sin( theta );\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = radius * Math.cos( theta );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixPosition: function ( m ) {\r\n\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 12 ];\r\n\t\t\tthis.y = e[ 13 ];\r\n\t\t\tthis.z = e[ 14 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixScale: function ( m ) {\r\n\r\n\t\t\tvar sx = this.setFromMatrixColumn( m, 0 ).length();\r\n\t\t\tvar sy = this.setFromMatrixColumn( m, 1 ).length();\r\n\t\t\tvar sz = this.setFromMatrixColumn( m, 2 ).length();\r\n\r\n\t\t\tthis.x = sx;\r\n\t\t\tthis.y = sy;\r\n\t\t\tthis.z = sz;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrixColumn: function ( m, index ) {\r\n\r\n\t\t\treturn this.fromArray( m.elements, index * 4 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\t\t\tthis.z = array[ offset + 2 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\t\t\tarray[ offset + 2 ] = this.z;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\t\t\tthis.z = attribute.getZ( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t * @author tschw\r\n\t */\r\n\r\n\tvar _vector$1 = new Vector3();\r\n\r\n\tfunction Matrix3() {\r\n\r\n\t\tthis.elements = [\r\n\r\n\t\t\t1, 0, 0,\r\n\t\t\t0, 1, 0,\r\n\t\t\t0, 0, 1\r\n\r\n\t\t];\r\n\r\n\t\tif ( arguments.length > 0 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Matrix3.prototype, {\r\n\r\n\t\tisMatrix3: true,\r\n\r\n\t\tset: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;\r\n\t\t\tte[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;\r\n\t\t\tte[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tidentity: function () {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0,\r\n\t\t\t\t0, 1, 0,\r\n\t\t\t\t0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().fromArray( this.elements );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];\r\n\t\t\tte[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];\r\n\t\t\tte[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrix4: function ( m ) {\r\n\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tme[ 0 ], me[ 4 ], me[ 8 ],\r\n\t\t\t\tme[ 1 ], me[ 5 ], me[ 9 ],\r\n\t\t\t\tme[ 2 ], me[ 6 ], me[ 10 ]\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyToBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$1.x = attribute.getX( i );\r\n\t\t\t\t_vector$1.y = attribute.getY( i );\r\n\t\t\t\t_vector$1.z = attribute.getZ( i );\r\n\r\n\t\t\t\t_vector$1.applyMatrix3( this );\r\n\r\n\t\t\t\tattribute.setXYZ( i, _vector$1.x, _vector$1.y, _vector$1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn attribute;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( this, m );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( m, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyMatrices: function ( a, b ) {\r\n\r\n\t\t\tvar ae = a.elements;\r\n\t\t\tvar be = b.elements;\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];\r\n\t\t\tvar a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];\r\n\t\t\tvar a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];\r\n\r\n\t\t\tvar b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];\r\n\t\t\tvar b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];\r\n\t\t\tvar b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];\r\n\r\n\t\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;\r\n\t\t\tte[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;\r\n\t\t\tte[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;\r\n\r\n\t\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;\r\n\t\t\tte[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;\r\n\t\t\tte[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;\r\n\r\n\t\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;\r\n\t\t\tte[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;\r\n\t\t\tte[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;\r\n\t\t\tte[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;\r\n\t\t\tte[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdeterminant: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],\r\n\t\t\t\td = te[ 3 ], e = te[ 4 ], f = te[ 5 ],\r\n\t\t\t\tg = te[ 6 ], h = te[ 7 ], i = te[ 8 ];\r\n\r\n\t\t\treturn a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;\r\n\r\n\t\t},\r\n\r\n\t\tgetInverse: function ( matrix, throwOnDegenerate ) {\r\n\r\n\t\t\tif ( matrix && matrix.isMatrix4 ) {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument.\" );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar me = matrix.elements,\r\n\t\t\t\tte = this.elements,\r\n\r\n\t\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],\r\n\t\t\t\tn12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],\r\n\t\t\t\tn13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],\r\n\r\n\t\t\t\tt11 = n33 * n22 - n32 * n23,\r\n\t\t\t\tt12 = n32 * n13 - n33 * n12,\r\n\t\t\t\tt13 = n23 * n12 - n22 * n13,\r\n\r\n\t\t\t\tdet = n11 * t11 + n21 * t12 + n31 * t13;\r\n\r\n\t\t\tif ( det === 0 ) {\r\n\r\n\t\t\t\tvar msg = \"THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0\";\r\n\r\n\t\t\t\tif ( throwOnDegenerate === true ) {\r\n\r\n\t\t\t\t\tthrow new Error( msg );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( msg );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this.identity();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar detInv = 1 / det;\r\n\r\n\t\t\tte[ 0 ] = t11 * detInv;\r\n\t\t\tte[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;\r\n\t\t\tte[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;\r\n\r\n\t\t\tte[ 3 ] = t12 * detInv;\r\n\t\t\tte[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;\r\n\t\t\tte[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;\r\n\r\n\t\t\tte[ 6 ] = t13 * detInv;\r\n\t\t\tte[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;\r\n\t\t\tte[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranspose: function () {\r\n\r\n\t\t\tvar tmp, m = this.elements;\r\n\r\n\t\t\ttmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;\r\n\t\t\ttmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;\r\n\t\t\ttmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetNormalMatrix: function ( matrix4 ) {\r\n\r\n\t\t\treturn this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();\r\n\r\n\t\t},\r\n\r\n\t\ttransposeIntoArray: function ( r ) {\r\n\r\n\t\t\tvar m = this.elements;\r\n\r\n\t\t\tr[ 0 ] = m[ 0 ];\r\n\t\t\tr[ 1 ] = m[ 3 ];\r\n\t\t\tr[ 2 ] = m[ 6 ];\r\n\t\t\tr[ 3 ] = m[ 1 ];\r\n\t\t\tr[ 4 ] = m[ 4 ];\r\n\t\t\tr[ 5 ] = m[ 7 ];\r\n\t\t\tr[ 6 ] = m[ 2 ];\r\n\t\t\tr[ 7 ] = m[ 5 ];\r\n\t\t\tr[ 8 ] = m[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {\r\n\r\n\t\t\tvar c = Math.cos( rotation );\r\n\t\t\tvar s = Math.sin( rotation );\r\n\r\n\t\t\tthis.set(\r\n\t\t\t\tsx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,\r\n\t\t\t\t- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,\r\n\t\t\t\t0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( sx, sy ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;\r\n\t\t\tte[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotate: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta );\r\n\t\t\tvar s = Math.sin( theta );\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];\r\n\t\t\tvar a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];\r\n\r\n\t\t\tte[ 0 ] = c * a11 + s * a21;\r\n\t\t\tte[ 3 ] = c * a12 + s * a22;\r\n\t\t\tte[ 6 ] = c * a13 + s * a23;\r\n\r\n\t\t\tte[ 1 ] = - s * a11 + c * a21;\r\n\t\t\tte[ 4 ] = - s * a12 + c * a22;\r\n\t\t\tte[ 7 ] = - s * a13 + c * a23;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( tx, ty ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];\r\n\t\t\tte[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( matrix ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = matrix.elements;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tif ( te[ i ] !== me[ i ] ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.elements[ i ] = array[ i + offset ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tarray[ offset ] = te[ 0 ];\r\n\t\t\tarray[ offset + 1 ] = te[ 1 ];\r\n\t\t\tarray[ offset + 2 ] = te[ 2 ];\r\n\r\n\t\t\tarray[ offset + 3 ] = te[ 3 ];\r\n\t\t\tarray[ offset + 4 ] = te[ 4 ];\r\n\t\t\tarray[ offset + 5 ] = te[ 5 ];\r\n\r\n\t\t\tarray[ offset + 6 ] = te[ 6 ];\r\n\t\t\tarray[ offset + 7 ] = te[ 7 ];\r\n\t\t\tarray[ offset + 8 ] = te[ 8 ];\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t */\r\n\r\n\tvar _canvas;\r\n\r\n\tvar ImageUtils = {\r\n\r\n\t\tgetDataURL: function ( image ) {\r\n\r\n\t\t\tvar canvas;\r\n\r\n\t\t\tif ( typeof HTMLCanvasElement == 'undefined' ) {\r\n\r\n\t\t\t\treturn image.src;\r\n\r\n\t\t\t} else if ( image instanceof HTMLCanvasElement ) {\r\n\r\n\t\t\t\tcanvas = image;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( _canvas === undefined ) { _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); }\r\n\r\n\t\t\t\t_canvas.width = image.width;\r\n\t\t\t\t_canvas.height = image.height;\r\n\r\n\t\t\t\tvar context = _canvas.getContext( '2d' );\r\n\r\n\t\t\t\tif ( image instanceof ImageData ) {\r\n\r\n\t\t\t\t\tcontext.putImageData( image, 0, 0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tcontext.drawImage( image, 0, 0, image.width, image.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcanvas = _canvas;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( canvas.width > 2048 || canvas.height > 2048 ) {\r\n\r\n\t\t\t\treturn canvas.toDataURL( 'image/jpeg', 0.6 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn canvas.toDataURL( 'image/png' );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t */\r\n\r\n\tvar textureId = 0;\r\n\r\n\tfunction Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: textureId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;\r\n\t\tthis.mipmaps = [];\r\n\r\n\t\tthis.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;\r\n\r\n\t\tthis.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;\r\n\t\tthis.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;\r\n\r\n\t\tthis.anisotropy = anisotropy !== undefined ? anisotropy : 1;\r\n\r\n\t\tthis.format = format !== undefined ? format : RGBAFormat;\r\n\t\tthis.type = type !== undefined ? type : UnsignedByteType;\r\n\r\n\t\tthis.offset = new Vector2( 0, 0 );\r\n\t\tthis.repeat = new Vector2( 1, 1 );\r\n\t\tthis.center = new Vector2( 0, 0 );\r\n\t\tthis.rotation = 0;\r\n\r\n\t\tthis.matrixAutoUpdate = true;\r\n\t\tthis.matrix = new Matrix3();\r\n\r\n\t\tthis.generateMipmaps = true;\r\n\t\tthis.premultiplyAlpha = false;\r\n\t\tthis.flipY = true;\r\n\t\tthis.unpackAlignment = 4;\t// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)\r\n\r\n\t\t// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.\r\n\t\t//\r\n\t\t// Also changing the encoding after already used by a Material will not automatically make the Material\r\n\t\t// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.\r\n\t\tthis.encoding = encoding !== undefined ? encoding : LinearEncoding;\r\n\r\n\t\tthis.version = 0;\r\n\t\tthis.onUpdate = null;\r\n\r\n\t}\r\n\r\n\tTexture.DEFAULT_IMAGE = undefined;\r\n\tTexture.DEFAULT_MAPPING = UVMapping;\r\n\r\n\tTexture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Texture,\r\n\r\n\t\tisTexture: true,\r\n\r\n\t\tupdateMatrix: function () {\r\n\r\n\t\t\tthis.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.image = source.image;\r\n\t\t\tthis.mipmaps = source.mipmaps.slice( 0 );\r\n\r\n\t\t\tthis.mapping = source.mapping;\r\n\r\n\t\t\tthis.wrapS = source.wrapS;\r\n\t\t\tthis.wrapT = source.wrapT;\r\n\r\n\t\t\tthis.magFilter = source.magFilter;\r\n\t\t\tthis.minFilter = source.minFilter;\r\n\r\n\t\t\tthis.anisotropy = source.anisotropy;\r\n\r\n\t\t\tthis.format = source.format;\r\n\t\t\tthis.type = source.type;\r\n\r\n\t\t\tthis.offset.copy( source.offset );\r\n\t\t\tthis.repeat.copy( source.repeat );\r\n\t\t\tthis.center.copy( source.center );\r\n\t\t\tthis.rotation = source.rotation;\r\n\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\t\t\tthis.matrix.copy( source.matrix );\r\n\r\n\t\t\tthis.generateMipmaps = source.generateMipmaps;\r\n\t\t\tthis.premultiplyAlpha = source.premultiplyAlpha;\r\n\t\t\tthis.flipY = source.flipY;\r\n\t\t\tthis.unpackAlignment = source.unpackAlignment;\r\n\t\t\tthis.encoding = source.encoding;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tif ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {\r\n\r\n\t\t\t\treturn meta.textures[ this.uuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar output = {\r\n\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Texture',\r\n\t\t\t\t\tgenerator: 'Texture.toJSON'\r\n\t\t\t\t},\r\n\r\n\t\t\t\tuuid: this.uuid,\r\n\t\t\t\tname: this.name,\r\n\r\n\t\t\t\tmapping: this.mapping,\r\n\r\n\t\t\t\trepeat: [ this.repeat.x, this.repeat.y ],\r\n\t\t\t\toffset: [ this.offset.x, this.offset.y ],\r\n\t\t\t\tcenter: [ this.center.x, this.center.y ],\r\n\t\t\t\trotation: this.rotation,\r\n\r\n\t\t\t\twrap: [ this.wrapS, this.wrapT ],\r\n\r\n\t\t\t\tformat: this.format,\r\n\t\t\t\ttype: this.type,\r\n\t\t\t\tencoding: this.encoding,\r\n\r\n\t\t\t\tminFilter: this.minFilter,\r\n\t\t\t\tmagFilter: this.magFilter,\r\n\t\t\t\tanisotropy: this.anisotropy,\r\n\r\n\t\t\t\tflipY: this.flipY,\r\n\r\n\t\t\t\tpremultiplyAlpha: this.premultiplyAlpha,\r\n\t\t\t\tunpackAlignment: this.unpackAlignment\r\n\r\n\t\t\t};\r\n\r\n\t\t\tif ( this.image !== undefined ) {\r\n\r\n\t\t\t\t// TODO: Move to THREE.Image\r\n\r\n\t\t\t\tvar image = this.image;\r\n\r\n\t\t\t\tif ( image.uuid === undefined ) {\r\n\r\n\t\t\t\t\timage.uuid = _Math.generateUUID(); // UGH\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\tvar url;\r\n\r\n\t\t\t\t\tif ( Array.isArray( image ) ) {\r\n\r\n\t\t\t\t\t\t// process array of images e.g. CubeTexture\r\n\r\n\t\t\t\t\t\turl = [];\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, l = image.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\turl.push( ImageUtils.getDataURL( image[ i ] ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// process single image\r\n\r\n\t\t\t\t\t\turl = ImageUtils.getDataURL( image );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmeta.images[ image.uuid ] = {\r\n\t\t\t\t\t\tuuid: image.uuid,\r\n\t\t\t\t\t\turl: url\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\toutput.image = image.uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! isRootObject ) {\r\n\r\n\t\t\t\tmeta.textures[ this.uuid ] = output;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t},\r\n\r\n\t\ttransformUv: function ( uv ) {\r\n\r\n\t\t\tif ( this.mapping !== UVMapping ) { return uv; }\r\n\r\n\t\t\tuv.applyMatrix3( this.matrix );\r\n\r\n\t\t\tif ( uv.x < 0 || uv.x > 1 ) {\r\n\r\n\t\t\t\tswitch ( this.wrapS ) {\r\n\r\n\t\t\t\t\tcase RepeatWrapping:\r\n\r\n\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase ClampToEdgeWrapping:\r\n\r\n\t\t\t\t\t\tuv.x = uv.x < 0 ? 0 : 1;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase MirroredRepeatWrapping:\r\n\r\n\t\t\t\t\t\tif ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {\r\n\r\n\t\t\t\t\t\t\tuv.x = Math.ceil( uv.x ) - uv.x;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv.y < 0 || uv.y > 1 ) {\r\n\r\n\t\t\t\tswitch ( this.wrapT ) {\r\n\r\n\t\t\t\t\tcase RepeatWrapping:\r\n\r\n\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase ClampToEdgeWrapping:\r\n\r\n\t\t\t\t\t\tuv.y = uv.y < 0 ? 0 : 1;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase MirroredRepeatWrapping:\r\n\r\n\t\t\t\t\t\tif ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {\r\n\r\n\t\t\t\t\t\t\tuv.y = Math.ceil( uv.y ) - uv.y;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.flipY ) {\r\n\r\n\t\t\t\tuv.y = 1 - uv.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn uv;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Texture.prototype, \"needsUpdate\", {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author egraether / http://egraether.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Vector4( x, y, z, w ) {\r\n\r\n\t\tthis.x = x || 0;\r\n\t\tthis.y = y || 0;\r\n\t\tthis.z = z || 0;\r\n\t\tthis.w = ( w !== undefined ) ? w : 1;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( Vector4.prototype, {\r\n\r\n\t\t\"width\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.z = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t\"height\": {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.w;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis.w = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector4.prototype, {\r\n\r\n\t\tisVector4: true,\r\n\r\n\t\tset: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis.x = x;\r\n\t\t\tthis.y = y;\r\n\t\t\tthis.z = z;\r\n\t\t\tthis.w = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x = scalar;\r\n\t\t\tthis.y = scalar;\r\n\t\t\tthis.z = scalar;\r\n\t\t\tthis.w = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( x ) {\r\n\r\n\t\t\tthis.x = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( y ) {\r\n\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( z ) {\r\n\r\n\t\t\tthis.z = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( w ) {\r\n\r\n\t\t\tthis.w = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponent: function ( index, value ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: this.x = value; break;\r\n\t\t\t\tcase 1: this.y = value; break;\r\n\t\t\t\tcase 2: this.z = value; break;\r\n\t\t\t\tcase 3: this.w = value; break;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetComponent: function ( index ) {\r\n\r\n\t\t\tswitch ( index ) {\r\n\r\n\t\t\t\tcase 0: return this.x;\r\n\t\t\t\tcase 1: return this.y;\r\n\t\t\t\tcase 2: return this.z;\r\n\t\t\t\tcase 3: return this.w;\r\n\t\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.x, this.y, this.z, this.w );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( v ) {\r\n\r\n\t\t\tthis.x = v.x;\r\n\t\t\tthis.y = v.y;\r\n\t\t\tthis.z = v.z;\r\n\t\t\tthis.w = ( v.w !== undefined ) ? v.w : 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.addVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x += v.x;\r\n\t\t\tthis.y += v.y;\r\n\t\t\tthis.z += v.z;\r\n\t\t\tthis.w += v.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.x += s;\r\n\t\t\tthis.y += s;\r\n\t\t\tthis.z += s;\r\n\t\t\tthis.w += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x + b.x;\r\n\t\t\tthis.y = a.y + b.y;\r\n\t\t\tthis.z = a.z + b.z;\r\n\t\t\tthis.w = a.w + b.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScaledVector: function ( v, s ) {\r\n\r\n\t\t\tthis.x += v.x * s;\r\n\t\t\tthis.y += v.y * s;\r\n\t\t\tthis.z += v.z * s;\r\n\t\t\tthis.w += v.w * s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( v, w ) {\r\n\r\n\t\t\tif ( w !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\r\n\t\t\t\treturn this.subVectors( v, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x -= v.x;\r\n\t\t\tthis.y -= v.y;\r\n\t\t\tthis.z -= v.z;\r\n\t\t\tthis.w -= v.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubScalar: function ( s ) {\r\n\r\n\t\t\tthis.x -= s;\r\n\t\t\tthis.y -= s;\r\n\t\t\tthis.z -= s;\r\n\t\t\tthis.w -= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsubVectors: function ( a, b ) {\r\n\r\n\t\t\tthis.x = a.x - b.x;\r\n\t\t\tthis.y = a.y - b.y;\r\n\t\t\tthis.z = a.z - b.z;\r\n\t\t\tthis.w = a.w - b.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.x *= scalar;\r\n\t\t\tthis.y *= scalar;\r\n\t\t\tthis.z *= scalar;\r\n\t\t\tthis.w *= scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tvar x = this.x, y = this.y, z = this.z, w = this.w;\r\n\t\t\tvar e = m.elements;\r\n\r\n\t\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;\r\n\t\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;\r\n\t\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;\r\n\t\t\tthis.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdivideScalar: function ( scalar ) {\r\n\r\n\t\t\treturn this.multiplyScalar( 1 / scalar );\r\n\r\n\t\t},\r\n\r\n\t\tsetAxisAngleFromQuaternion: function ( q ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\r\n\r\n\t\t\t// q is assumed to be normalized\r\n\r\n\t\t\tthis.w = 2 * Math.acos( q.w );\r\n\r\n\t\t\tvar s = Math.sqrt( 1 - q.w * q.w );\r\n\r\n\t\t\tif ( s < 0.0001 ) {\r\n\r\n\t\t\t\tthis.x = 1;\r\n\t\t\t\tthis.y = 0;\r\n\t\t\t\tthis.z = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.x = q.x / s;\r\n\t\t\t\tthis.y = q.y / s;\r\n\t\t\t\tthis.z = q.z / s;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetAxisAngleFromRotationMatrix: function ( m ) {\r\n\r\n\t\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar angle, x, y, z,\t\t// variables for result\r\n\t\t\t\tepsilon = 0.01,\t\t// margin to allow for rounding errors\r\n\t\t\t\tepsilon2 = 0.1,\t\t// margin to distinguish between 0 and 180 degrees\r\n\r\n\t\t\t\tte = m.elements,\r\n\r\n\t\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\r\n\t\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\r\n\t\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\r\n\r\n\t\t\tif ( ( Math.abs( m12 - m21 ) < epsilon ) &&\r\n\t\t\t ( Math.abs( m13 - m31 ) < epsilon ) &&\r\n\t\t\t ( Math.abs( m23 - m32 ) < epsilon ) ) {\r\n\r\n\t\t\t\t// singularity found\r\n\t\t\t\t// first check for identity matrix which must have +1 for all terms\r\n\t\t\t\t// in leading diagonal and zero in other terms\r\n\r\n\t\t\t\tif ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m13 + m31 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m23 + m32 ) < epsilon2 ) &&\r\n\t\t\t\t ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {\r\n\r\n\t\t\t\t\t// this singularity is identity matrix so angle = 0\r\n\r\n\t\t\t\t\tthis.set( 1, 0, 0, 0 );\r\n\r\n\t\t\t\t\treturn this; // zero angle, arbitrary axis\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// otherwise this singularity is angle = 180\r\n\r\n\t\t\t\tangle = Math.PI;\r\n\r\n\t\t\t\tvar xx = ( m11 + 1 ) / 2;\r\n\t\t\t\tvar yy = ( m22 + 1 ) / 2;\r\n\t\t\t\tvar zz = ( m33 + 1 ) / 2;\r\n\t\t\t\tvar xy = ( m12 + m21 ) / 4;\r\n\t\t\t\tvar xz = ( m13 + m31 ) / 4;\r\n\t\t\t\tvar yz = ( m23 + m32 ) / 4;\r\n\r\n\t\t\t\tif ( ( xx > yy ) && ( xx > zz ) ) {\r\n\r\n\t\t\t\t\t// m11 is the largest diagonal term\r\n\r\n\t\t\t\t\tif ( xx < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0;\r\n\t\t\t\t\t\ty = 0.707106781;\r\n\t\t\t\t\t\tz = 0.707106781;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tx = Math.sqrt( xx );\r\n\t\t\t\t\t\ty = xy / x;\r\n\t\t\t\t\t\tz = xz / x;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( yy > zz ) {\r\n\r\n\t\t\t\t\t// m22 is the largest diagonal term\r\n\r\n\t\t\t\t\tif ( yy < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0.707106781;\r\n\t\t\t\t\t\ty = 0;\r\n\t\t\t\t\t\tz = 0.707106781;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ty = Math.sqrt( yy );\r\n\t\t\t\t\t\tx = xy / y;\r\n\t\t\t\t\t\tz = yz / y;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// m33 is the largest diagonal term so base result on this\r\n\r\n\t\t\t\t\tif ( zz < epsilon ) {\r\n\r\n\t\t\t\t\t\tx = 0.707106781;\r\n\t\t\t\t\t\ty = 0.707106781;\r\n\t\t\t\t\t\tz = 0;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tz = Math.sqrt( zz );\r\n\t\t\t\t\t\tx = xz / z;\r\n\t\t\t\t\t\ty = yz / z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.set( x, y, z, angle );\r\n\r\n\t\t\t\treturn this; // return 180 deg rotation\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// as we have reached here there are no singularities so we can handle normally\r\n\r\n\t\t\tvar s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +\r\n\t\t\t ( m13 - m31 ) * ( m13 - m31 ) +\r\n\t\t\t ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize\r\n\r\n\t\t\tif ( Math.abs( s ) < 0.001 ) { s = 1; }\r\n\r\n\t\t\t// prevent divide by zero, should not happen if matrix is orthogonal and should be\r\n\t\t\t// caught by singularity test above, but I've left it in just in case\r\n\r\n\t\t\tthis.x = ( m32 - m23 ) / s;\r\n\t\t\tthis.y = ( m13 - m31 ) / s;\r\n\t\t\tthis.z = ( m21 - m12 ) / s;\r\n\t\t\tthis.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmin: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.min( this.x, v.x );\r\n\t\t\tthis.y = Math.min( this.y, v.y );\r\n\t\t\tthis.z = Math.min( this.z, v.z );\r\n\t\t\tthis.w = Math.min( this.w, v.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmax: function ( v ) {\r\n\r\n\t\t\tthis.x = Math.max( this.x, v.x );\r\n\t\t\tthis.y = Math.max( this.y, v.y );\r\n\t\t\tthis.z = Math.max( this.z, v.z );\r\n\t\t\tthis.w = Math.max( this.w, v.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclamp: function ( min, max ) {\r\n\r\n\t\t\t// assumes min < max, componentwise\r\n\r\n\t\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\r\n\t\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\r\n\t\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\r\n\t\t\tthis.w = Math.max( min.w, Math.min( max.w, this.w ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampScalar: function ( minVal, maxVal ) {\r\n\r\n\t\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\r\n\t\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\r\n\t\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\r\n\t\t\tthis.w = Math.max( minVal, Math.min( maxVal, this.w ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclampLength: function ( min, max ) {\r\n\r\n\t\t\tvar length = this.length();\r\n\r\n\t\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\r\n\r\n\t\t},\r\n\r\n\t\tfloor: function () {\r\n\r\n\t\t\tthis.x = Math.floor( this.x );\r\n\t\t\tthis.y = Math.floor( this.y );\r\n\t\t\tthis.z = Math.floor( this.z );\r\n\t\t\tthis.w = Math.floor( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tceil: function () {\r\n\r\n\t\t\tthis.x = Math.ceil( this.x );\r\n\t\t\tthis.y = Math.ceil( this.y );\r\n\t\t\tthis.z = Math.ceil( this.z );\r\n\t\t\tthis.w = Math.ceil( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tround: function () {\r\n\r\n\t\t\tthis.x = Math.round( this.x );\r\n\t\t\tthis.y = Math.round( this.y );\r\n\t\t\tthis.z = Math.round( this.z );\r\n\t\t\tthis.w = Math.round( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\troundToZero: function () {\r\n\r\n\t\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\r\n\t\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\r\n\t\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\r\n\t\t\tthis.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.x = - this.x;\r\n\t\t\tthis.y = - this.y;\r\n\t\t\tthis.z = - this.z;\r\n\t\t\tthis.w = - this.w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdot: function ( v ) {\r\n\r\n\t\t\treturn this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\r\n\r\n\t\t},\r\n\r\n\t\tlengthSq: function () {\r\n\r\n\t\t\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\r\n\r\n\t\t},\r\n\r\n\t\tlength: function () {\r\n\r\n\t\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );\r\n\r\n\t\t},\r\n\r\n\t\tmanhattanLength: function () {\r\n\r\n\t\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\treturn this.divideScalar( this.length() || 1 );\r\n\r\n\t\t},\r\n\r\n\t\tsetLength: function ( length ) {\r\n\r\n\t\t\treturn this.normalize().multiplyScalar( length );\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( v, alpha ) {\r\n\r\n\t\t\tthis.x += ( v.x - this.x ) * alpha;\r\n\t\t\tthis.y += ( v.y - this.y ) * alpha;\r\n\t\t\tthis.z += ( v.z - this.z ) * alpha;\r\n\t\t\tthis.w += ( v.w - this.w ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpVectors: function ( v1, v2, alpha ) {\r\n\r\n\t\t\treturn this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( v ) {\r\n\r\n\t\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.x = array[ offset ];\r\n\t\t\tthis.y = array[ offset + 1 ];\r\n\t\t\tthis.z = array[ offset + 2 ];\r\n\t\t\tthis.w = array[ offset + 3 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.x;\r\n\t\t\tarray[ offset + 1 ] = this.y;\r\n\t\t\tarray[ offset + 2 ] = this.z;\r\n\t\t\tarray[ offset + 3 ] = this.w;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tif ( offset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.x = attribute.getX( index );\r\n\t\t\tthis.y = attribute.getY( index );\r\n\t\t\tthis.z = attribute.getZ( index );\r\n\t\t\tthis.w = attribute.getW( index );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author szimek / https://github.com/szimek/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author Marius Kintel / https://github.com/kintel\r\n\t */\r\n\r\n\t/*\r\n\t In options, we can specify:\r\n\t * Texture parameters for an auto-generated target texture\r\n\t * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers\r\n\t*/\r\n\tfunction WebGLRenderTarget( width, height, options ) {\r\n\r\n\t\tthis.width = width;\r\n\t\tthis.height = height;\r\n\r\n\t\tthis.scissor = new Vector4( 0, 0, width, height );\r\n\t\tthis.scissorTest = false;\r\n\r\n\t\tthis.viewport = new Vector4( 0, 0, width, height );\r\n\r\n\t\toptions = options || {};\r\n\r\n\t\tthis.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );\r\n\r\n\t\tthis.texture.image = {};\r\n\t\tthis.texture.image.width = width;\r\n\t\tthis.texture.image.height = height;\r\n\r\n\t\tthis.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;\r\n\t\tthis.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;\r\n\r\n\t\tthis.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;\r\n\t\tthis.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;\r\n\t\tthis.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;\r\n\r\n\t}\r\n\r\n\tWebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: WebGLRenderTarget,\r\n\r\n\t\tisWebGLRenderTarget: true,\r\n\r\n\t\tsetSize: function ( width, height ) {\r\n\r\n\t\t\tif ( this.width !== width || this.height !== height ) {\r\n\r\n\t\t\t\tthis.width = width;\r\n\t\t\t\tthis.height = height;\r\n\r\n\t\t\t\tthis.texture.image.width = width;\r\n\t\t\t\tthis.texture.image.height = height;\r\n\r\n\t\t\t\tthis.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.viewport.set( 0, 0, width, height );\r\n\t\t\tthis.scissor.set( 0, 0, width, height );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.width = source.width;\r\n\t\t\tthis.height = source.height;\r\n\r\n\t\t\tthis.viewport.copy( source.viewport );\r\n\r\n\t\t\tthis.texture = source.texture.clone();\r\n\r\n\t\t\tthis.depthBuffer = source.depthBuffer;\r\n\t\t\tthis.stencilBuffer = source.stencilBuffer;\r\n\t\t\tthis.depthTexture = source.depthTexture;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author Matt DesLauriers / @mattdesl\r\n\t */\r\n\r\n\tfunction WebGLMultisampleRenderTarget( width, height, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t\tthis.samples = 4;\r\n\r\n\t}\r\n\r\n\tWebGLMultisampleRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {\r\n\r\n\t\tconstructor: WebGLMultisampleRenderTarget,\r\n\r\n\t\tisWebGLMultisampleRenderTarget: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tWebGLRenderTarget.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.samples = source.samples;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _v1 = new Vector3();\r\n\tvar _m1 = new Matrix4();\r\n\tvar _zero = new Vector3( 0, 0, 0 );\r\n\tvar _one = new Vector3( 1, 1, 1 );\r\n\tvar _x = new Vector3();\r\n\tvar _y = new Vector3();\r\n\tvar _z = new Vector3();\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author philogb / http://blog.thejit.org/\r\n\t * @author jordi_ros / http://plattsoft.com\r\n\t * @author D1plo1d / http://github.com/D1plo1d\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author timknip / http://www.floorplanner.com/\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Matrix4() {\r\n\r\n\t\tthis.elements = [\r\n\r\n\t\t\t1, 0, 0, 0,\r\n\t\t\t0, 1, 0, 0,\r\n\t\t\t0, 0, 1, 0,\r\n\t\t\t0, 0, 0, 1\r\n\r\n\t\t];\r\n\r\n\t\tif ( arguments.length > 0 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Matrix4.prototype, {\r\n\r\n\t\tisMatrix4: true,\r\n\r\n\t\tset: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;\r\n\t\t\tte[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;\r\n\t\t\tte[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;\r\n\t\t\tte[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tidentity: function () {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, 0,\r\n\t\t\t\t0, 1, 0, 0,\r\n\t\t\t\t0, 0, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Matrix4().fromArray( this.elements );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];\r\n\t\t\tte[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];\r\n\t\t\tte[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];\r\n\t\t\tte[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyPosition: function ( m ) {\r\n\r\n\t\t\tvar te = this.elements, me = m.elements;\r\n\r\n\t\t\tte[ 12 ] = me[ 12 ];\r\n\t\t\tte[ 13 ] = me[ 13 ];\r\n\t\t\tte[ 14 ] = me[ 14 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\textractBasis: function ( xAxis, yAxis, zAxis ) {\r\n\r\n\t\t\txAxis.setFromMatrixColumn( this, 0 );\r\n\t\t\tyAxis.setFromMatrixColumn( this, 1 );\r\n\t\t\tzAxis.setFromMatrixColumn( this, 2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeBasis: function ( xAxis, yAxis, zAxis ) {\r\n\r\n\t\t\tthis.set(\r\n\t\t\t\txAxis.x, yAxis.x, zAxis.x, 0,\r\n\t\t\t\txAxis.y, yAxis.y, zAxis.y, 0,\r\n\t\t\t\txAxis.z, yAxis.z, zAxis.z, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\textractRotation: function ( m ) {\r\n\r\n\t\t\t// this method does not support reflection matrices\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = m.elements;\r\n\r\n\t\t\tvar scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();\r\n\t\t\tvar scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();\r\n\t\t\tvar scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();\r\n\r\n\t\t\tte[ 0 ] = me[ 0 ] * scaleX;\r\n\t\t\tte[ 1 ] = me[ 1 ] * scaleX;\r\n\t\t\tte[ 2 ] = me[ 2 ] * scaleX;\r\n\t\t\tte[ 3 ] = 0;\r\n\r\n\t\t\tte[ 4 ] = me[ 4 ] * scaleY;\r\n\t\t\tte[ 5 ] = me[ 5 ] * scaleY;\r\n\t\t\tte[ 6 ] = me[ 6 ] * scaleY;\r\n\t\t\tte[ 7 ] = 0;\r\n\r\n\t\t\tte[ 8 ] = me[ 8 ] * scaleZ;\r\n\t\t\tte[ 9 ] = me[ 9 ] * scaleZ;\r\n\t\t\tte[ 10 ] = me[ 10 ] * scaleZ;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\tte[ 12 ] = 0;\r\n\t\t\tte[ 13 ] = 0;\r\n\t\t\tte[ 14 ] = 0;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationFromEuler: function ( euler ) {\r\n\r\n\t\t\tif ( ! ( euler && euler.isEuler ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar x = euler.x, y = euler.y, z = euler.z;\r\n\t\t\tvar a = Math.cos( x ), b = Math.sin( x );\r\n\t\t\tvar c = Math.cos( y ), d = Math.sin( y );\r\n\t\t\tvar e = Math.cos( z ), f = Math.sin( z );\r\n\r\n\t\t\tif ( euler.order === 'XYZ' ) {\r\n\r\n\t\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = - c * f;\r\n\t\t\t\tte[ 8 ] = d;\r\n\r\n\t\t\t\tte[ 1 ] = af + be * d;\r\n\t\t\t\tte[ 5 ] = ae - bf * d;\r\n\t\t\t\tte[ 9 ] = - b * c;\r\n\r\n\t\t\t\tte[ 2 ] = bf - ae * d;\r\n\t\t\t\tte[ 6 ] = be + af * d;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'YXZ' ) {\r\n\r\n\t\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\r\n\r\n\t\t\t\tte[ 0 ] = ce + df * b;\r\n\t\t\t\tte[ 4 ] = de * b - cf;\r\n\t\t\t\tte[ 8 ] = a * d;\r\n\r\n\t\t\t\tte[ 1 ] = a * f;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = - b;\r\n\r\n\t\t\t\tte[ 2 ] = cf * b - de;\r\n\t\t\t\tte[ 6 ] = df + ce * b;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'ZXY' ) {\r\n\r\n\t\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\r\n\r\n\t\t\t\tte[ 0 ] = ce - df * b;\r\n\t\t\t\tte[ 4 ] = - a * f;\r\n\t\t\t\tte[ 8 ] = de + cf * b;\r\n\r\n\t\t\t\tte[ 1 ] = cf + de * b;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = df - ce * b;\r\n\r\n\t\t\t\tte[ 2 ] = - a * d;\r\n\t\t\t\tte[ 6 ] = b;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'ZYX' ) {\r\n\r\n\t\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = be * d - af;\r\n\t\t\t\tte[ 8 ] = ae * d + bf;\r\n\r\n\t\t\t\tte[ 1 ] = c * f;\r\n\t\t\t\tte[ 5 ] = bf * d + ae;\r\n\t\t\t\tte[ 9 ] = af * d - be;\r\n\r\n\t\t\t\tte[ 2 ] = - d;\r\n\t\t\t\tte[ 6 ] = b * c;\r\n\t\t\t\tte[ 10 ] = a * c;\r\n\r\n\t\t\t} else if ( euler.order === 'YZX' ) {\r\n\r\n\t\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = bd - ac * f;\r\n\t\t\t\tte[ 8 ] = bc * f + ad;\r\n\r\n\t\t\t\tte[ 1 ] = f;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = - b * e;\r\n\r\n\t\t\t\tte[ 2 ] = - d * e;\r\n\t\t\t\tte[ 6 ] = ad * f + bc;\r\n\t\t\t\tte[ 10 ] = ac - bd * f;\r\n\r\n\t\t\t} else if ( euler.order === 'XZY' ) {\r\n\r\n\t\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\r\n\r\n\t\t\t\tte[ 0 ] = c * e;\r\n\t\t\t\tte[ 4 ] = - f;\r\n\t\t\t\tte[ 8 ] = d * e;\r\n\r\n\t\t\t\tte[ 1 ] = ac * f + bd;\r\n\t\t\t\tte[ 5 ] = a * e;\r\n\t\t\t\tte[ 9 ] = ad * f - bc;\r\n\r\n\t\t\t\tte[ 2 ] = bc * f - ad;\r\n\t\t\t\tte[ 6 ] = b * e;\r\n\t\t\t\tte[ 10 ] = bd * f + ac;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bottom row\r\n\t\t\tte[ 3 ] = 0;\r\n\t\t\tte[ 7 ] = 0;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\t// last column\r\n\t\t\tte[ 12 ] = 0;\r\n\t\t\tte[ 13 ] = 0;\r\n\t\t\tte[ 14 ] = 0;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\treturn this.compose( _zero, q, _one );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( eye, target, up ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\t_z.subVectors( eye, target );\r\n\r\n\t\t\tif ( _z.lengthSq() === 0 ) {\r\n\r\n\t\t\t\t// eye and target are in the same position\r\n\r\n\t\t\t\t_z.z = 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_z.normalize();\r\n\t\t\t_x.crossVectors( up, _z );\r\n\r\n\t\t\tif ( _x.lengthSq() === 0 ) {\r\n\r\n\t\t\t\t// up and z are parallel\r\n\r\n\t\t\t\tif ( Math.abs( up.z ) === 1 ) {\r\n\r\n\t\t\t\t\t_z.x += 0.0001;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_z.z += 0.0001;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_z.normalize();\r\n\t\t\t\t_x.crossVectors( up, _z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_x.normalize();\r\n\t\t\t_y.crossVectors( _z, _x );\r\n\r\n\t\t\tte[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;\r\n\t\t\tte[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;\r\n\t\t\tte[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( m, n ) {\r\n\r\n\t\t\tif ( n !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );\r\n\t\t\t\treturn this.multiplyMatrices( m, n );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.multiplyMatrices( this, m );\r\n\r\n\t\t},\r\n\r\n\t\tpremultiply: function ( m ) {\r\n\r\n\t\t\treturn this.multiplyMatrices( m, this );\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyMatrices: function ( a, b ) {\r\n\r\n\t\t\tvar ae = a.elements;\r\n\t\t\tvar be = b.elements;\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];\r\n\t\t\tvar a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];\r\n\t\t\tvar a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];\r\n\t\t\tvar a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];\r\n\r\n\t\t\tvar b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];\r\n\t\t\tvar b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];\r\n\t\t\tvar b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];\r\n\t\t\tvar b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];\r\n\r\n\t\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;\r\n\t\t\tte[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;\r\n\t\t\tte[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;\r\n\t\t\tte[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;\r\n\r\n\t\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;\r\n\t\t\tte[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;\r\n\t\t\tte[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;\r\n\t\t\tte[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;\r\n\r\n\t\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;\r\n\t\t\tte[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;\r\n\t\t\tte[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;\r\n\t\t\tte[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;\r\n\r\n\t\t\tte[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;\r\n\t\t\tte[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;\r\n\t\t\tte[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;\r\n\t\t\tte[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tte[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;\r\n\t\t\tte[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;\r\n\t\t\tte[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;\r\n\t\t\tte[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyToBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_v1.x = attribute.getX( i );\r\n\t\t\t\t_v1.y = attribute.getY( i );\r\n\t\t\t\t_v1.z = attribute.getZ( i );\r\n\r\n\t\t\t\t_v1.applyMatrix4( this );\r\n\r\n\t\t\t\tattribute.setXYZ( i, _v1.x, _v1.y, _v1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn attribute;\r\n\r\n\t\t},\r\n\r\n\t\tdeterminant: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];\r\n\t\t\tvar n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];\r\n\t\t\tvar n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];\r\n\t\t\tvar n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];\r\n\r\n\t\t\t//TODO: make this more efficient\r\n\t\t\t//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )\r\n\r\n\t\t\treturn (\r\n\t\t\t\tn41 * (\r\n\t\t\t\t\t+ n14 * n23 * n32\r\n\t\t\t\t\t - n13 * n24 * n32\r\n\t\t\t\t\t - n14 * n22 * n33\r\n\t\t\t\t\t + n12 * n24 * n33\r\n\t\t\t\t\t + n13 * n22 * n34\r\n\t\t\t\t\t - n12 * n23 * n34\r\n\t\t\t\t) +\r\n\t\t\t\tn42 * (\r\n\t\t\t\t\t+ n11 * n23 * n34\r\n\t\t\t\t\t - n11 * n24 * n33\r\n\t\t\t\t\t + n14 * n21 * n33\r\n\t\t\t\t\t - n13 * n21 * n34\r\n\t\t\t\t\t + n13 * n24 * n31\r\n\t\t\t\t\t - n14 * n23 * n31\r\n\t\t\t\t) +\r\n\t\t\t\tn43 * (\r\n\t\t\t\t\t+ n11 * n24 * n32\r\n\t\t\t\t\t - n11 * n22 * n34\r\n\t\t\t\t\t - n14 * n21 * n32\r\n\t\t\t\t\t + n12 * n21 * n34\r\n\t\t\t\t\t + n14 * n22 * n31\r\n\t\t\t\t\t - n12 * n24 * n31\r\n\t\t\t\t) +\r\n\t\t\t\tn44 * (\r\n\t\t\t\t\t- n13 * n22 * n31\r\n\t\t\t\t\t - n11 * n23 * n32\r\n\t\t\t\t\t + n11 * n22 * n33\r\n\t\t\t\t\t + n13 * n21 * n32\r\n\t\t\t\t\t - n12 * n21 * n33\r\n\t\t\t\t\t + n12 * n23 * n31\r\n\t\t\t\t)\r\n\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\ttranspose: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar tmp;\r\n\r\n\t\t\ttmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;\r\n\t\t\ttmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;\r\n\t\t\ttmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;\r\n\r\n\t\t\ttmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;\r\n\t\t\ttmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;\r\n\t\t\ttmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetPosition: function ( x, y, z ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tif ( x.isVector3 ) {\r\n\r\n\t\t\t\tte[ 12 ] = x.x;\r\n\t\t\t\tte[ 13 ] = x.y;\r\n\t\t\t\tte[ 14 ] = x.z;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tte[ 12 ] = x;\r\n\t\t\t\tte[ 13 ] = y;\r\n\t\t\t\tte[ 14 ] = z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetInverse: function ( m, throwOnDegenerate ) {\r\n\r\n\t\t\t// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm\r\n\t\t\tvar te = this.elements,\r\n\t\t\t\tme = m.elements,\r\n\r\n\t\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],\r\n\t\t\t\tn12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],\r\n\t\t\t\tn13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],\r\n\t\t\t\tn14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],\r\n\r\n\t\t\t\tt11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,\r\n\t\t\t\tt12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,\r\n\t\t\t\tt13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,\r\n\t\t\t\tt14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;\r\n\r\n\t\t\tvar det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;\r\n\r\n\t\t\tif ( det === 0 ) {\r\n\r\n\t\t\t\tvar msg = \"THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0\";\r\n\r\n\t\t\t\tif ( throwOnDegenerate === true ) {\r\n\r\n\t\t\t\t\tthrow new Error( msg );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( msg );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this.identity();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar detInv = 1 / det;\r\n\r\n\t\t\tte[ 0 ] = t11 * detInv;\r\n\t\t\tte[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;\r\n\t\t\tte[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;\r\n\t\t\tte[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 4 ] = t12 * detInv;\r\n\t\t\tte[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;\r\n\t\t\tte[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;\r\n\t\t\tte[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 8 ] = t13 * detInv;\r\n\t\t\tte[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;\r\n\t\t\tte[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;\r\n\t\t\tte[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;\r\n\r\n\t\t\tte[ 12 ] = t14 * detInv;\r\n\t\t\tte[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;\r\n\t\t\tte[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;\r\n\t\t\tte[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( v ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar x = v.x, y = v.y, z = v.z;\r\n\r\n\t\t\tte[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;\r\n\t\t\tte[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;\r\n\t\t\tte[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;\r\n\t\t\tte[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMaxScaleOnAxis: function () {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];\r\n\t\t\tvar scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];\r\n\t\t\tvar scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];\r\n\r\n\t\t\treturn Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );\r\n\r\n\t\t},\r\n\r\n\t\tmakeTranslation: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, x,\r\n\t\t\t\t0, 1, 0, y,\r\n\t\t\t\t0, 0, 1, z,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationX: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, 0, 0, 0,\r\n\t\t\t\t0, c, - s, 0,\r\n\t\t\t\t0, s, c, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationY: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t c, 0, s, 0,\r\n\t\t\t\t 0, 1, 0, 0,\r\n\t\t\t\t- s, 0, c, 0,\r\n\t\t\t\t 0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationZ: function ( theta ) {\r\n\r\n\t\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tc, - s, 0, 0,\r\n\t\t\t\ts, c, 0, 0,\r\n\t\t\t\t0, 0, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeRotationAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// Based on http://www.gamedev.net/reference/articles/article1199.asp\r\n\r\n\t\t\tvar c = Math.cos( angle );\r\n\t\t\tvar s = Math.sin( angle );\r\n\t\t\tvar t = 1 - c;\r\n\t\t\tvar x = axis.x, y = axis.y, z = axis.z;\r\n\t\t\tvar tx = t * x, ty = t * y;\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\ttx * x + c, tx * y - s * z, tx * z + s * y, 0,\r\n\t\t\t\ttx * y + s * z, ty * y + c, ty * z - s * x, 0,\r\n\t\t\t\ttx * z - s * y, ty * z + s * x, t * z * z + c, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\t return this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeScale: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\tx, 0, 0, 0,\r\n\t\t\t\t0, y, 0, 0,\r\n\t\t\t\t0, 0, z, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeShear: function ( x, y, z ) {\r\n\r\n\t\t\tthis.set(\r\n\r\n\t\t\t\t1, y, z, 0,\r\n\t\t\t\tx, 1, z, 0,\r\n\t\t\t\tx, y, 1, 0,\r\n\t\t\t\t0, 0, 0, 1\r\n\r\n\t\t\t);\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcompose: function ( position, quaternion, scale ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;\r\n\t\t\tvar x2 = x + x,\ty2 = y + y, z2 = z + z;\r\n\t\t\tvar xx = x * x2, xy = x * y2, xz = x * z2;\r\n\t\t\tvar yy = y * y2, yz = y * z2, zz = z * z2;\r\n\t\t\tvar wx = w * x2, wy = w * y2, wz = w * z2;\r\n\r\n\t\t\tvar sx = scale.x, sy = scale.y, sz = scale.z;\r\n\r\n\t\t\tte[ 0 ] = ( 1 - ( yy + zz ) ) * sx;\r\n\t\t\tte[ 1 ] = ( xy + wz ) * sx;\r\n\t\t\tte[ 2 ] = ( xz - wy ) * sx;\r\n\t\t\tte[ 3 ] = 0;\r\n\r\n\t\t\tte[ 4 ] = ( xy - wz ) * sy;\r\n\t\t\tte[ 5 ] = ( 1 - ( xx + zz ) ) * sy;\r\n\t\t\tte[ 6 ] = ( yz + wx ) * sy;\r\n\t\t\tte[ 7 ] = 0;\r\n\r\n\t\t\tte[ 8 ] = ( xz + wy ) * sz;\r\n\t\t\tte[ 9 ] = ( yz - wx ) * sz;\r\n\t\t\tte[ 10 ] = ( 1 - ( xx + yy ) ) * sz;\r\n\t\t\tte[ 11 ] = 0;\r\n\r\n\t\t\tte[ 12 ] = position.x;\r\n\t\t\tte[ 13 ] = position.y;\r\n\t\t\tte[ 14 ] = position.z;\r\n\t\t\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdecompose: function ( position, quaternion, scale ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tvar sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();\r\n\t\t\tvar sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();\r\n\t\t\tvar sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();\r\n\r\n\t\t\t// if determine is negative, we need to invert one scale\r\n\t\t\tvar det = this.determinant();\r\n\t\t\tif ( det < 0 ) { sx = - sx; }\r\n\r\n\t\t\tposition.x = te[ 12 ];\r\n\t\t\tposition.y = te[ 13 ];\r\n\t\t\tposition.z = te[ 14 ];\r\n\r\n\t\t\t// scale the rotation part\r\n\t\t\t_m1.copy( this );\r\n\r\n\t\t\tvar invSX = 1 / sx;\r\n\t\t\tvar invSY = 1 / sy;\r\n\t\t\tvar invSZ = 1 / sz;\r\n\r\n\t\t\t_m1.elements[ 0 ] *= invSX;\r\n\t\t\t_m1.elements[ 1 ] *= invSX;\r\n\t\t\t_m1.elements[ 2 ] *= invSX;\r\n\r\n\t\t\t_m1.elements[ 4 ] *= invSY;\r\n\t\t\t_m1.elements[ 5 ] *= invSY;\r\n\t\t\t_m1.elements[ 6 ] *= invSY;\r\n\r\n\t\t\t_m1.elements[ 8 ] *= invSZ;\r\n\t\t\t_m1.elements[ 9 ] *= invSZ;\r\n\t\t\t_m1.elements[ 10 ] *= invSZ;\r\n\r\n\t\t\tquaternion.setFromRotationMatrix( _m1 );\r\n\r\n\t\t\tscale.x = sx;\r\n\t\t\tscale.y = sy;\r\n\t\t\tscale.z = sz;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakePerspective: function ( left, right, top, bottom, near, far ) {\r\n\r\n\t\t\tif ( far === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar x = 2 * near / ( right - left );\r\n\t\t\tvar y = 2 * near / ( top - bottom );\r\n\r\n\t\t\tvar a = ( right + left ) / ( right - left );\r\n\t\t\tvar b = ( top + bottom ) / ( top - bottom );\r\n\t\t\tvar c = - ( far + near ) / ( far - near );\r\n\t\t\tvar d = - 2 * far * near / ( far - near );\r\n\r\n\t\t\tte[ 0 ] = x;\tte[ 4 ] = 0;\tte[ 8 ] = a;\tte[ 12 ] = 0;\r\n\t\t\tte[ 1 ] = 0;\tte[ 5 ] = y;\tte[ 9 ] = b;\tte[ 13 ] = 0;\r\n\t\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = c;\tte[ 14 ] = d;\r\n\t\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = - 1;\tte[ 15 ] = 0;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeOrthographic: function ( left, right, top, bottom, near, far ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar w = 1.0 / ( right - left );\r\n\t\t\tvar h = 1.0 / ( top - bottom );\r\n\t\t\tvar p = 1.0 / ( far - near );\r\n\r\n\t\t\tvar x = ( right + left ) * w;\r\n\t\t\tvar y = ( top + bottom ) * h;\r\n\t\t\tvar z = ( far + near ) * p;\r\n\r\n\t\t\tte[ 0 ] = 2 * w;\tte[ 4 ] = 0;\tte[ 8 ] = 0;\tte[ 12 ] = - x;\r\n\t\t\tte[ 1 ] = 0;\tte[ 5 ] = 2 * h;\tte[ 9 ] = 0;\tte[ 13 ] = - y;\r\n\t\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = - 2 * p;\tte[ 14 ] = - z;\r\n\t\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = 0;\tte[ 15 ] = 1;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( matrix ) {\r\n\r\n\t\t\tvar te = this.elements;\r\n\t\t\tvar me = matrix.elements;\r\n\r\n\t\t\tfor ( var i = 0; i < 16; i ++ ) {\r\n\r\n\t\t\t\tif ( te[ i ] !== me[ i ] ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tfor ( var i = 0; i < 16; i ++ ) {\r\n\r\n\t\t\t\tthis.elements[ i ] = array[ i + offset ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar te = this.elements;\r\n\r\n\t\t\tarray[ offset ] = te[ 0 ];\r\n\t\t\tarray[ offset + 1 ] = te[ 1 ];\r\n\t\t\tarray[ offset + 2 ] = te[ 2 ];\r\n\t\t\tarray[ offset + 3 ] = te[ 3 ];\r\n\r\n\t\t\tarray[ offset + 4 ] = te[ 4 ];\r\n\t\t\tarray[ offset + 5 ] = te[ 5 ];\r\n\t\t\tarray[ offset + 6 ] = te[ 6 ];\r\n\t\t\tarray[ offset + 7 ] = te[ 7 ];\r\n\r\n\t\t\tarray[ offset + 8 ] = te[ 8 ];\r\n\t\t\tarray[ offset + 9 ] = te[ 9 ];\r\n\t\t\tarray[ offset + 10 ] = te[ 10 ];\r\n\t\t\tarray[ offset + 11 ] = te[ 11 ];\r\n\r\n\t\t\tarray[ offset + 12 ] = te[ 12 ];\r\n\t\t\tarray[ offset + 13 ] = te[ 13 ];\r\n\t\t\tarray[ offset + 14 ] = te[ 14 ];\r\n\t\t\tarray[ offset + 15 ] = te[ 15 ];\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _matrix = new Matrix4();\r\n\tvar _quaternion$1 = new Quaternion();\r\n\r\n\tfunction Euler( x, y, z, order ) {\r\n\r\n\t\tthis._x = x || 0;\r\n\t\tthis._y = y || 0;\r\n\t\tthis._z = z || 0;\r\n\t\tthis._order = order || Euler.DefaultOrder;\r\n\r\n\t}\r\n\r\n\tEuler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];\r\n\r\n\tEuler.DefaultOrder = 'XYZ';\r\n\r\n\tObject.defineProperties( Euler.prototype, {\r\n\r\n\t\tx: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._x;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._x = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ty: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._y;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._y = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tz: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._z;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._z = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\torder: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this._order;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tthis._order = value;\r\n\t\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Euler.prototype, {\r\n\r\n\t\tisEuler: true,\r\n\r\n\t\tset: function ( x, y, z, order ) {\r\n\r\n\t\t\tthis._x = x;\r\n\t\t\tthis._y = y;\r\n\t\t\tthis._z = z;\r\n\t\t\tthis._order = order || this._order;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this._x, this._y, this._z, this._order );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( euler ) {\r\n\r\n\t\t\tthis._x = euler._x;\r\n\t\t\tthis._y = euler._y;\r\n\t\t\tthis._z = euler._z;\r\n\t\t\tthis._order = euler._order;\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromRotationMatrix: function ( m, order, update ) {\r\n\r\n\t\t\tvar clamp = _Math.clamp;\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tvar te = m.elements;\r\n\t\t\tvar m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];\r\n\t\t\tvar m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];\r\n\t\t\tvar m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\r\n\r\n\t\t\torder = order || this._order;\r\n\r\n\t\t\tif ( order === 'XYZ' ) {\r\n\r\n\t\t\t\tthis._y = Math.asin( clamp( m13, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m13 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\r\n\t\t\t\t\tthis._z = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'YXZ' ) {\r\n\r\n\t\t\t\tthis._x = Math.asin( - clamp( m23, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m23 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m22 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\r\n\t\t\t\t\tthis._z = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'ZXY' ) {\r\n\r\n\t\t\t\tthis._x = Math.asin( clamp( m32, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m32 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._y = 0;\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'ZYX' ) {\r\n\r\n\t\t\t\tthis._y = Math.asin( - clamp( m31, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m31 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m33 );\r\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'YZX' ) {\r\n\r\n\t\t\t\tthis._z = Math.asin( clamp( m21, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m21 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m22 );\r\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = 0;\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( order === 'XZY' ) {\r\n\r\n\t\t\t\tthis._z = Math.asin( - clamp( m12, - 1, 1 ) );\r\n\r\n\t\t\t\tif ( Math.abs( m12 ) < 0.9999999 ) {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\r\n\t\t\t\t\tthis._y = Math.atan2( m13, m11 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\r\n\t\t\t\t\tthis._y = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._order = order;\r\n\r\n\t\t\tif ( update !== false ) { this._onChangeCallback(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromQuaternion: function ( q, order, update ) {\r\n\r\n\t\t\t_matrix.makeRotationFromQuaternion( q );\r\n\r\n\t\t\treturn this.setFromRotationMatrix( _matrix, order, update );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v, order ) {\r\n\r\n\t\t\treturn this.set( v.x, v.y, v.z, order || this._order );\r\n\r\n\t\t},\r\n\r\n\t\treorder: function ( newOrder ) {\r\n\r\n\t\t\t// WARNING: this discards revolution information -bhouston\r\n\r\n\t\t\t_quaternion$1.setFromEuler( this );\r\n\r\n\t\t\treturn this.setFromQuaternion( _quaternion$1, newOrder );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( euler ) {\r\n\r\n\t\t\treturn ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array ) {\r\n\r\n\t\t\tthis._x = array[ 0 ];\r\n\t\t\tthis._y = array[ 1 ];\r\n\t\t\tthis._z = array[ 2 ];\r\n\t\t\tif ( array[ 3 ] !== undefined ) { this._order = array[ 3 ]; }\r\n\r\n\t\t\tthis._onChangeCallback();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this._x;\r\n\t\t\tarray[ offset + 1 ] = this._y;\r\n\t\t\tarray[ offset + 2 ] = this._z;\r\n\t\t\tarray[ offset + 3 ] = this._order;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\ttoVector3: function ( optionalResult ) {\r\n\r\n\t\t\tif ( optionalResult ) {\r\n\r\n\t\t\t\treturn optionalResult.set( this._x, this._y, this._z );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn new Vector3( this._x, this._y, this._z );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_onChange: function ( callback ) {\r\n\r\n\t\t\tthis._onChangeCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t_onChangeCallback: function () {}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Layers() {\r\n\r\n\t\tthis.mask = 1 | 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Layers.prototype, {\r\n\r\n\t\tset: function ( channel ) {\r\n\r\n\t\t\tthis.mask = 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tenable: function ( channel ) {\r\n\r\n\t\t\tthis.mask |= 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tenableAll: function () {\r\n\r\n\t\t\tthis.mask = 0xffffffff | 0;\r\n\r\n\t\t},\r\n\r\n\t\ttoggle: function ( channel ) {\r\n\r\n\t\t\tthis.mask ^= 1 << channel | 0;\r\n\r\n\t\t},\r\n\r\n\t\tdisable: function ( channel ) {\r\n\r\n\t\t\tthis.mask &= ~ ( 1 << channel | 0 );\r\n\r\n\t\t},\r\n\r\n\t\tdisableAll: function () {\r\n\r\n\t\t\tthis.mask = 0;\r\n\r\n\t\t},\r\n\r\n\t\ttest: function ( layers ) {\r\n\r\n\t\t\treturn ( this.mask & layers.mask ) !== 0;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _object3DId = 0;\r\n\r\n\tvar _v1$1 = new Vector3();\r\n\tvar _q1 = new Quaternion();\r\n\tvar _m1$1 = new Matrix4();\r\n\tvar _target = new Vector3();\r\n\r\n\tvar _position = new Vector3();\r\n\tvar _scale = new Vector3();\r\n\tvar _quaternion$2 = new Quaternion();\r\n\r\n\tvar _xAxis = new Vector3( 1, 0, 0 );\r\n\tvar _yAxis = new Vector3( 0, 1, 0 );\r\n\tvar _zAxis = new Vector3( 0, 0, 1 );\r\n\r\n\tvar _addedEvent = { type: 'added' };\r\n\tvar _removedEvent = { type: 'removed' };\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author elephantatwork / www.elephantatwork.ch\r\n\t */\r\n\r\n\tfunction Object3D() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _object3DId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Object3D';\r\n\r\n\t\tthis.parent = null;\r\n\t\tthis.children = [];\r\n\r\n\t\tthis.up = Object3D.DefaultUp.clone();\r\n\r\n\t\tvar position = new Vector3();\r\n\t\tvar rotation = new Euler();\r\n\t\tvar quaternion = new Quaternion();\r\n\t\tvar scale = new Vector3( 1, 1, 1 );\r\n\r\n\t\tfunction onRotationChange() {\r\n\r\n\t\t\tquaternion.setFromEuler( rotation, false );\r\n\r\n\t\t}\r\n\r\n\t\tfunction onQuaternionChange() {\r\n\r\n\t\t\trotation.setFromQuaternion( quaternion, undefined, false );\r\n\r\n\t\t}\r\n\r\n\t\trotation._onChange( onRotationChange );\r\n\t\tquaternion._onChange( onQuaternionChange );\r\n\r\n\t\tObject.defineProperties( this, {\r\n\t\t\tposition: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: position\r\n\t\t\t},\r\n\t\t\trotation: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: rotation\r\n\t\t\t},\r\n\t\t\tquaternion: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: quaternion\r\n\t\t\t},\r\n\t\t\tscale: {\r\n\t\t\t\tconfigurable: true,\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: scale\r\n\t\t\t},\r\n\t\t\tmodelViewMatrix: {\r\n\t\t\t\tvalue: new Matrix4()\r\n\t\t\t},\r\n\t\t\tnormalMatrix: {\r\n\t\t\t\tvalue: new Matrix3()\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.matrix = new Matrix4();\r\n\t\tthis.matrixWorld = new Matrix4();\r\n\r\n\t\tthis.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;\r\n\t\tthis.matrixWorldNeedsUpdate = false;\r\n\r\n\t\tthis.layers = new Layers();\r\n\t\tthis.visible = true;\r\n\r\n\t\tthis.castShadow = false;\r\n\t\tthis.receiveShadow = false;\r\n\r\n\t\tthis.frustumCulled = true;\r\n\t\tthis.renderOrder = 0;\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t}\r\n\r\n\tObject3D.DefaultUp = new Vector3( 0, 1, 0 );\r\n\tObject3D.DefaultMatrixAutoUpdate = true;\r\n\r\n\tObject3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Object3D,\r\n\r\n\t\tisObject3D: true,\r\n\r\n\t\tonBeforeRender: function () {},\r\n\t\tonAfterRender: function () {},\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tthis.matrix.premultiply( matrix );\r\n\r\n\t\t\tthis.matrix.decompose( this.position, this.quaternion, this.scale );\r\n\r\n\t\t},\r\n\r\n\t\tapplyQuaternion: function ( q ) {\r\n\r\n\t\t\tthis.quaternion.premultiply( q );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromAxisAngle: function ( axis, angle ) {\r\n\r\n\t\t\t// assumes axis is normalized\r\n\r\n\t\t\tthis.quaternion.setFromAxisAngle( axis, angle );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromEuler: function ( euler ) {\r\n\r\n\t\t\tthis.quaternion.setFromEuler( euler, true );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromMatrix: function ( m ) {\r\n\r\n\t\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\r\n\r\n\t\t\tthis.quaternion.setFromRotationMatrix( m );\r\n\r\n\t\t},\r\n\r\n\t\tsetRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\t// assumes q is normalized\r\n\r\n\t\t\tthis.quaternion.copy( q );\r\n\r\n\t\t},\r\n\r\n\t\trotateOnAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// rotate object on axis in object space\r\n\t\t\t// axis is assumed to be normalized\r\n\r\n\t\t\t_q1.setFromAxisAngle( axis, angle );\r\n\r\n\t\t\tthis.quaternion.multiply( _q1 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateOnWorldAxis: function ( axis, angle ) {\r\n\r\n\t\t\t// rotate object on axis in world space\r\n\t\t\t// axis is assumed to be normalized\r\n\t\t\t// method assumes no rotated parent\r\n\r\n\t\t\t_q1.setFromAxisAngle( axis, angle );\r\n\r\n\t\t\tthis.quaternion.premultiply( _q1 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _xAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _yAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\treturn this.rotateOnAxis( _zAxis, angle );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateOnAxis: function ( axis, distance ) {\r\n\r\n\t\t\t// translate object by distance along axis in object space\r\n\t\t\t// axis is assumed to be normalized\r\n\r\n\t\t\t_v1$1.copy( axis ).applyQuaternion( this.quaternion );\r\n\r\n\t\t\tthis.position.add( _v1$1.multiplyScalar( distance ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslateX: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _xAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateY: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _yAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\ttranslateZ: function ( distance ) {\r\n\r\n\t\t\treturn this.translateOnAxis( _zAxis, distance );\r\n\r\n\t\t},\r\n\r\n\t\tlocalToWorld: function ( vector ) {\r\n\r\n\t\t\treturn vector.applyMatrix4( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tworldToLocal: function ( vector ) {\r\n\r\n\t\t\treturn vector.applyMatrix4( _m1$1.getInverse( this.matrixWorld ) );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( x, y, z ) {\r\n\r\n\t\t\t// This method does not support objects having non-uniformly-scaled parent(s)\r\n\r\n\t\t\tif ( x.isVector3 ) {\r\n\r\n\t\t\t\t_target.copy( x );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_target.set( x, y, z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tthis.updateWorldMatrix( true, false );\r\n\r\n\t\t\t_position.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\tif ( this.isCamera || this.isLight ) {\r\n\r\n\t\t\t\t_m1$1.lookAt( _position, _target, this.up );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_m1$1.lookAt( _target, _position, this.up );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.quaternion.setFromRotationMatrix( _m1$1 );\r\n\r\n\t\t\tif ( parent ) {\r\n\r\n\t\t\t\t_m1$1.extractRotation( parent.matrixWorld );\r\n\t\t\t\t_q1.setFromRotationMatrix( _m1$1 );\r\n\t\t\t\tthis.quaternion.premultiply( _q1.inverse() );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( object ) {\r\n\r\n\t\t\tif ( arguments.length > 1 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\r\n\r\n\t\t\t\t\tthis.add( arguments[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object === this ) {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Object3D.add: object can't be added as a child of itself.\", object );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( object && object.isObject3D ) ) {\r\n\r\n\t\t\t\tif ( object.parent !== null ) {\r\n\r\n\t\t\t\t\tobject.parent.remove( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tobject.parent = this;\r\n\t\t\t\tthis.children.push( object );\r\n\r\n\t\t\t\tobject.dispatchEvent( _addedEvent );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.error( \"THREE.Object3D.add: object not an instance of THREE.Object3D.\", object );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tremove: function ( object ) {\r\n\r\n\t\t\tif ( arguments.length > 1 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\r\n\r\n\t\t\t\t\tthis.remove( arguments[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar index = this.children.indexOf( object );\r\n\r\n\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\tobject.parent = null;\r\n\t\t\t\tthis.children.splice( index, 1 );\r\n\r\n\t\t\t\tobject.dispatchEvent( _removedEvent );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tattach: function ( object ) {\r\n\r\n\t\t\t// adds object as a child of this, while maintaining the object's world transform\r\n\r\n\t\t\tthis.updateWorldMatrix( true, false );\r\n\r\n\t\t\t_m1$1.getInverse( this.matrixWorld );\r\n\r\n\t\t\tif ( object.parent !== null ) {\r\n\r\n\t\t\t\tobject.parent.updateWorldMatrix( true, false );\r\n\r\n\t\t\t\t_m1$1.multiply( object.parent.matrixWorld );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.applyMatrix( _m1$1 );\r\n\r\n\t\t\tobject.updateWorldMatrix( false, false );\r\n\r\n\t\t\tthis.add( object );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectById: function ( id ) {\r\n\r\n\t\t\treturn this.getObjectByProperty( 'id', id );\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectByName: function ( name ) {\r\n\r\n\t\t\treturn this.getObjectByProperty( 'name', name );\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectByProperty: function ( name, value ) {\r\n\r\n\t\t\tif ( this[ name ] === value ) { return this; }\r\n\r\n\t\t\tfor ( var i = 0, l = this.children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar child = this.children[ i ];\r\n\t\t\t\tvar object = child.getObjectByProperty( name, value );\r\n\r\n\t\t\t\tif ( object !== undefined ) {\r\n\r\n\t\t\t\t\treturn object;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldPosition: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\treturn target.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldQuaternion: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );\r\n\t\t\t\ttarget = new Quaternion();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position, target, _scale );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldScale: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldScale() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position, _quaternion$2, target );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldDirection: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tvar e = this.matrixWorld.elements;\r\n\r\n\t\t\treturn target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\traycast: function () {},\r\n\r\n\t\ttraverse: function ( callback ) {\r\n\r\n\t\t\tcallback( this );\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].traverse( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttraverseVisible: function ( callback ) {\r\n\r\n\t\t\tif ( this.visible === false ) { return; }\r\n\r\n\t\t\tcallback( this );\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].traverseVisible( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttraverseAncestors: function ( callback ) {\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tif ( parent !== null ) {\r\n\r\n\t\t\t\tcallback( parent );\r\n\r\n\t\t\t\tparent.traverseAncestors( callback );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrix: function () {\r\n\r\n\t\t\tthis.matrix.compose( this.position, this.quaternion, this.scale );\r\n\r\n\t\t\tthis.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tif ( this.matrixWorldNeedsUpdate || force ) {\r\n\r\n\t\t\t\tif ( this.parent === null ) {\r\n\r\n\t\t\t\t\tthis.matrixWorld.copy( this.matrix );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.matrixWorldNeedsUpdate = false;\r\n\r\n\t\t\t\tforce = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update children\r\n\r\n\t\t\tvar children = this.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( force );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\r\n\r\n\t\t\tvar parent = this.parent;\r\n\r\n\t\t\tif ( updateParents === true && parent !== null ) {\r\n\r\n\t\t\t\tparent.updateWorldMatrix( true, false );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.matrixAutoUpdate ) { this.updateMatrix(); }\r\n\r\n\t\t\tif ( this.parent === null ) {\r\n\r\n\t\t\t\tthis.matrixWorld.copy( this.matrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update children\r\n\r\n\t\t\tif ( updateChildren === true ) {\r\n\r\n\t\t\t\tvar children = this.children;\r\n\r\n\t\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tchildren[ i ].updateWorldMatrix( false, true );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\t// meta is a string when called from JSON.stringify\r\n\t\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tvar output = {};\r\n\r\n\t\t\t// meta is a hash used to collect geometries, materials.\r\n\t\t\t// not providing it implies that this is the root object\r\n\t\t\t// being serialized.\r\n\t\t\tif ( isRootObject ) {\r\n\r\n\t\t\t\t// initialize meta obj\r\n\t\t\t\tmeta = {\r\n\t\t\t\t\tgeometries: {},\r\n\t\t\t\t\tmaterials: {},\r\n\t\t\t\t\ttextures: {},\r\n\t\t\t\t\timages: {},\r\n\t\t\t\t\tshapes: {}\r\n\t\t\t\t};\r\n\r\n\t\t\t\toutput.metadata = {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Object',\r\n\t\t\t\t\tgenerator: 'Object3D.toJSON'\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// standard Object3D serialization\r\n\r\n\t\t\tvar object = {};\r\n\r\n\t\t\tobject.uuid = this.uuid;\r\n\t\t\tobject.type = this.type;\r\n\r\n\t\t\tif ( this.name !== '' ) { object.name = this.name; }\r\n\t\t\tif ( this.castShadow === true ) { object.castShadow = true; }\r\n\t\t\tif ( this.receiveShadow === true ) { object.receiveShadow = true; }\r\n\t\t\tif ( this.visible === false ) { object.visible = false; }\r\n\t\t\tif ( this.frustumCulled === false ) { object.frustumCulled = false; }\r\n\t\t\tif ( this.renderOrder !== 0 ) { object.renderOrder = this.renderOrder; }\r\n\t\t\tif ( JSON.stringify( this.userData ) !== '{}' ) { object.userData = this.userData; }\r\n\r\n\t\t\tobject.layers = this.layers.mask;\r\n\t\t\tobject.matrix = this.matrix.toArray();\r\n\r\n\t\t\tif ( this.matrixAutoUpdate === false ) { object.matrixAutoUpdate = false; }\r\n\r\n\t\t\t// object specific properties\r\n\r\n\t\t\tif ( this.isInstancedMesh ) {\r\n\r\n\t\t\t\tobject.type = 'InstancedMesh';\r\n\t\t\t\tobject.count = this.count;\r\n\t\t\t\tobject.instanceMatrix = this.instanceMatrix.toJSON();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfunction serialize( library, element ) {\r\n\r\n\t\t\t\tif ( library[ element.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\tlibrary[ element.uuid ] = element.toJSON( meta );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn element.uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.isMesh || this.isLine || this.isPoints ) {\r\n\r\n\t\t\t\tobject.geometry = serialize( meta.geometries, this.geometry );\r\n\r\n\t\t\t\tvar parameters = this.geometry.parameters;\r\n\r\n\t\t\t\tif ( parameters !== undefined && parameters.shapes !== undefined ) {\r\n\r\n\t\t\t\t\tvar shapes = parameters.shapes;\r\n\r\n\t\t\t\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\t\t\t\tserialize( meta.shapes, shape );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tserialize( meta.shapes, shapes );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.material !== undefined ) {\r\n\r\n\t\t\t\tif ( Array.isArray( this.material ) ) {\r\n\r\n\t\t\t\t\tvar uuids = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = this.material.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\tuuids.push( serialize( meta.materials, this.material[ i ] ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tobject.material = uuids;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tobject.material = serialize( meta.materials, this.material );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.children.length > 0 ) {\r\n\r\n\t\t\t\tobject.children = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < this.children.length; i ++ ) {\r\n\r\n\t\t\t\t\tobject.children.push( this.children[ i ].toJSON( meta ).object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isRootObject ) {\r\n\r\n\t\t\t\tvar geometries = extractFromCache( meta.geometries );\r\n\t\t\t\tvar materials = extractFromCache( meta.materials );\r\n\t\t\t\tvar textures = extractFromCache( meta.textures );\r\n\t\t\t\tvar images = extractFromCache( meta.images );\r\n\t\t\t\tvar shapes = extractFromCache( meta.shapes );\r\n\r\n\t\t\t\tif ( geometries.length > 0 ) { output.geometries = geometries; }\r\n\t\t\t\tif ( materials.length > 0 ) { output.materials = materials; }\r\n\t\t\t\tif ( textures.length > 0 ) { output.textures = textures; }\r\n\t\t\t\tif ( images.length > 0 ) { output.images = images; }\r\n\t\t\t\tif ( shapes.length > 0 ) { output.shapes = shapes; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\toutput.object = object;\r\n\r\n\t\t\treturn output;\r\n\r\n\t\t\t// extract data from the cache hash\r\n\t\t\t// remove metadata on each item\r\n\t\t\t// and return as array\r\n\t\t\tfunction extractFromCache( cache ) {\r\n\r\n\t\t\t\tvar values = [];\r\n\t\t\t\tfor ( var key in cache ) {\r\n\r\n\t\t\t\t\tvar data = cache[ key ];\r\n\t\t\t\t\tdelete data.metadata;\r\n\t\t\t\t\tvalues.push( data );\r\n\r\n\t\t\t\t}\r\n\t\t\t\treturn values;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function ( recursive ) {\r\n\r\n\t\t\treturn new this.constructor().copy( this, recursive );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tif ( recursive === undefined ) { recursive = true; }\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.up.copy( source.up );\r\n\r\n\t\t\tthis.position.copy( source.position );\r\n\t\t\tthis.quaternion.copy( source.quaternion );\r\n\t\t\tthis.scale.copy( source.scale );\r\n\r\n\t\t\tthis.matrix.copy( source.matrix );\r\n\t\t\tthis.matrixWorld.copy( source.matrixWorld );\r\n\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\t\t\tthis.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;\r\n\r\n\t\t\tthis.layers.mask = source.layers.mask;\r\n\t\t\tthis.visible = source.visible;\r\n\r\n\t\t\tthis.castShadow = source.castShadow;\r\n\t\t\tthis.receiveShadow = source.receiveShadow;\r\n\r\n\t\t\tthis.frustumCulled = source.frustumCulled;\r\n\t\t\tthis.renderOrder = source.renderOrder;\r\n\r\n\t\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\r\n\r\n\t\t\tif ( recursive === true ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < source.children.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar child = source.children[ i ];\r\n\t\t\t\t\tthis.add( child.clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Scene() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Scene';\r\n\r\n\t\tthis.background = null;\r\n\t\tthis.fog = null;\r\n\t\tthis.overrideMaterial = null;\r\n\r\n\t\tthis.autoUpdate = true; // checked by the renderer\r\n\r\n\t\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tScene.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Scene,\r\n\r\n\t\tisScene: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tif ( source.background !== null ) { this.background = source.background.clone(); }\r\n\t\t\tif ( source.fog !== null ) { this.fog = source.fog.clone(); }\r\n\t\t\tif ( source.overrideMaterial !== null ) { this.overrideMaterial = source.overrideMaterial.clone(); }\r\n\r\n\t\t\tthis.autoUpdate = source.autoUpdate;\r\n\t\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tif ( this.background !== null ) { data.object.background = this.background.toJSON( meta ); }\r\n\t\t\tif ( this.fog !== null ) { data.object.fog = this.fog.toJSON(); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _points = [\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3(),\r\n\t\tnew Vector3()\r\n\t];\r\n\r\n\tvar _vector$2 = new Vector3();\r\n\r\n\tvar _box = new Box3();\r\n\r\n\t// triangle centered vertices\r\n\r\n\tvar _v0 = new Vector3();\r\n\tvar _v1$2 = new Vector3();\r\n\tvar _v2 = new Vector3();\r\n\r\n\t// triangle edge vectors\r\n\r\n\tvar _f0 = new Vector3();\r\n\tvar _f1 = new Vector3();\r\n\tvar _f2 = new Vector3();\r\n\r\n\tvar _center = new Vector3();\r\n\tvar _extents = new Vector3();\r\n\tvar _triangleNormal = new Vector3();\r\n\tvar _testAxis = new Vector3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Box3( min, max ) {\r\n\r\n\t\tthis.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );\r\n\t\tthis.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );\r\n\r\n\t}\r\n\r\n\r\n\tObject.assign( Box3.prototype, {\r\n\r\n\t\tisBox3: true,\r\n\r\n\t\tset: function ( min, max ) {\r\n\r\n\t\t\tthis.min.copy( min );\r\n\t\t\tthis.max.copy( max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromArray: function ( array ) {\r\n\r\n\t\t\tvar minX = + Infinity;\r\n\t\t\tvar minY = + Infinity;\r\n\t\t\tvar minZ = + Infinity;\r\n\r\n\t\t\tvar maxX = - Infinity;\r\n\t\t\tvar maxY = - Infinity;\r\n\t\t\tvar maxZ = - Infinity;\r\n\r\n\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\r\n\r\n\t\t\t\tvar x = array[ i ];\r\n\t\t\t\tvar y = array[ i + 1 ];\r\n\t\t\t\tvar z = array[ i + 2 ];\r\n\r\n\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\tif ( z < minZ ) { minZ = z; }\r\n\r\n\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\t\t\t\tif ( z > maxZ ) { maxZ = z; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.min.set( minX, minY, minZ );\r\n\t\t\tthis.max.set( maxX, maxY, maxZ );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromBufferAttribute: function ( attribute ) {\r\n\r\n\t\t\tvar minX = + Infinity;\r\n\t\t\tvar minY = + Infinity;\r\n\t\t\tvar minZ = + Infinity;\r\n\r\n\t\t\tvar maxX = - Infinity;\r\n\t\t\tvar maxY = - Infinity;\r\n\t\t\tvar maxZ = - Infinity;\r\n\r\n\t\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar x = attribute.getX( i );\r\n\t\t\t\tvar y = attribute.getY( i );\r\n\t\t\t\tvar z = attribute.getZ( i );\r\n\r\n\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\tif ( z < minZ ) { minZ = z; }\r\n\r\n\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\t\t\t\tif ( z > maxZ ) { maxZ = z; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.min.set( minX, minY, minZ );\r\n\t\t\tthis.max.set( maxX, maxY, maxZ );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByPoint( points[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCenterAndSize: function ( center, size ) {\r\n\r\n\t\t\tvar halfSize = _vector$2.copy( size ).multiplyScalar( 0.5 );\r\n\r\n\t\t\tthis.min.copy( center ).sub( halfSize );\r\n\t\t\tthis.max.copy( center ).add( halfSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromObject: function ( object ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\treturn this.expandByObject( object );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( box ) {\r\n\r\n\t\t\tthis.min.copy( box.min );\r\n\t\t\tthis.max.copy( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeEmpty: function () {\r\n\r\n\t\t\tthis.min.x = this.min.y = this.min.z = + Infinity;\r\n\t\t\tthis.max.x = this.max.y = this.max.z = - Infinity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tisEmpty: function () {\r\n\r\n\t\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\r\n\r\n\t\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tgetSize: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getSize() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );\r\n\r\n\t\t},\r\n\r\n\t\texpandByPoint: function ( point ) {\r\n\r\n\t\t\tthis.min.min( point );\r\n\t\t\tthis.max.max( point );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByVector: function ( vector ) {\r\n\r\n\t\t\tthis.min.sub( vector );\r\n\t\t\tthis.max.add( vector );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.min.addScalar( - scalar );\r\n\t\t\tthis.max.addScalar( scalar );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByObject: function ( object ) {\r\n\r\n\t\t\t// Computes the world-axis-aligned bounding box of an object (including its children),\r\n\t\t\t// accounting for both the object's, and children's, world transforms\r\n\r\n\t\t\tobject.updateWorldMatrix( false, false );\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( geometry !== undefined ) {\r\n\r\n\t\t\t\tif ( geometry.boundingBox === null ) {\r\n\r\n\t\t\t\t\tgeometry.computeBoundingBox();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_box.copy( geometry.boundingBox );\r\n\t\t\t\t_box.applyMatrix4( object.matrixWorld );\r\n\r\n\t\t\t\tthis.expandByPoint( _box.min );\r\n\t\t\t\tthis.expandByPoint( _box.max );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByObject( children[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn point.x < this.min.x || point.x > this.max.x ||\r\n\t\t\t\tpoint.y < this.min.y || point.y > this.max.y ||\r\n\t\t\t\tpoint.z < this.min.z || point.z > this.max.z ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsBox: function ( box ) {\r\n\r\n\t\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\r\n\t\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y &&\r\n\t\t\t\tthis.min.z <= box.min.z && box.max.z <= this.max.z;\r\n\r\n\t\t},\r\n\r\n\t\tgetParameter: function ( point, target ) {\r\n\r\n\t\t\t// This can potentially have a divide by zero if the box\r\n\t\t\t// has a size dimension of 0.\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .getParameter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set(\r\n\t\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\r\n\t\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y ),\r\n\t\t\t\t( point.z - this.min.z ) / ( this.max.z - this.min.z )\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\t// using 6 splitting planes to rule out intersections.\r\n\t\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\r\n\t\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ||\r\n\t\t\t\tbox.max.z < this.min.z || box.min.z > this.max.z ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\t// Find the point on the AABB closest to the sphere center.\r\n\t\t\tthis.clampPoint( sphere.center, _vector$2 );\r\n\r\n\t\t\t// If that point is inside the sphere, the AABB and sphere intersect.\r\n\t\t\treturn _vector$2.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\t// We compute the minimum and maximum dot product values. If those values\r\n\t\t\t// are on the same side (back or front) of the plane, then there is no intersection.\r\n\r\n\t\t\tvar min, max;\r\n\r\n\t\t\tif ( plane.normal.x > 0 ) {\r\n\r\n\t\t\t\tmin = plane.normal.x * this.min.x;\r\n\t\t\t\tmax = plane.normal.x * this.max.x;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin = plane.normal.x * this.max.x;\r\n\t\t\t\tmax = plane.normal.x * this.min.x;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( plane.normal.y > 0 ) {\r\n\r\n\t\t\t\tmin += plane.normal.y * this.min.y;\r\n\t\t\t\tmax += plane.normal.y * this.max.y;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin += plane.normal.y * this.max.y;\r\n\t\t\t\tmax += plane.normal.y * this.min.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( plane.normal.z > 0 ) {\r\n\r\n\t\t\t\tmin += plane.normal.z * this.min.z;\r\n\t\t\t\tmax += plane.normal.z * this.max.z;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmin += plane.normal.z * this.max.z;\r\n\t\t\t\tmax += plane.normal.z * this.min.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn ( min <= - plane.constant && max >= - plane.constant );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsTriangle: function ( triangle ) {\r\n\r\n\t\t\tif ( this.isEmpty() ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// compute box center and extents\r\n\t\t\tthis.getCenter( _center );\r\n\t\t\t_extents.subVectors( this.max, _center );\r\n\r\n\t\t\t// translate triangle to aabb origin\r\n\t\t\t_v0.subVectors( triangle.a, _center );\r\n\t\t\t_v1$2.subVectors( triangle.b, _center );\r\n\t\t\t_v2.subVectors( triangle.c, _center );\r\n\r\n\t\t\t// compute edge vectors for triangle\r\n\t\t\t_f0.subVectors( _v1$2, _v0 );\r\n\t\t\t_f1.subVectors( _v2, _v1$2 );\r\n\t\t\t_f2.subVectors( _v0, _v2 );\r\n\r\n\t\t\t// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb\r\n\t\t\t// make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation\r\n\t\t\t// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)\r\n\t\t\tvar axes = [\r\n\t\t\t\t0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,\r\n\t\t\t\t_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,\r\n\t\t\t\t- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0\r\n\t\t\t];\r\n\t\t\tif ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// test 3 face normals from the aabb\r\n\t\t\taxes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];\r\n\t\t\tif ( ! satForAxes( axes, _v0, _v1$2, _v2, _extents ) ) {\r\n\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// finally testing the face normal of the triangle\r\n\t\t\t// use already existing triangle edge vectors here\r\n\t\t\t_triangleNormal.crossVectors( _f0, _f1 );\r\n\t\t\taxes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];\r\n\r\n\t\t\treturn satForAxes( axes, _v0, _v1$2, _v2, _extents );\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box3: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\tvar clampedPoint = _vector$2.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t\treturn clampedPoint.sub( point ).length();\r\n\r\n\t\t},\r\n\r\n\t\tgetBoundingSphere: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Box3: .getBoundingSphere() target is now required' );\r\n\t\t\t\t//target = new Sphere(); // removed to avoid cyclic dependency\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.getCenter( target.center );\r\n\r\n\t\t\ttarget.radius = this.getSize( _vector$2 ).length() * 0.5;\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tintersect: function ( box ) {\r\n\r\n\t\t\tthis.min.max( box.min );\r\n\t\t\tthis.max.min( box.max );\r\n\r\n\t\t\t// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.\r\n\t\t\tif ( this.isEmpty() ) { this.makeEmpty(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tunion: function ( box ) {\r\n\r\n\t\t\tthis.min.min( box.min );\r\n\t\t\tthis.max.max( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\t// transform of empty box is an empty box.\r\n\t\t\tif ( this.isEmpty() ) { return this; }\r\n\r\n\t\t\t// NOTE: I am using a binary pattern to specify all 2^3 combinations below\r\n\t\t\t_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000\r\n\t\t\t_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001\r\n\t\t\t_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010\r\n\t\t\t_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011\r\n\t\t\t_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100\r\n\t\t\t_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101\r\n\t\t\t_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110\r\n\t\t\t_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111\r\n\r\n\t\t\tthis.setFromPoints( _points );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.min.add( offset );\r\n\t\t\tthis.max.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( box ) {\r\n\r\n\t\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction satForAxes( axes, v0, v1, v2, extents ) {\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tfor ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {\r\n\r\n\t\t\t_testAxis.fromArray( axes, i );\r\n\t\t\t// project the aabb onto the seperating axis\r\n\t\t\tvar r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );\r\n\t\t\t// project all 3 vertices of the triangle onto the seperating axis\r\n\t\t\tvar p0 = v0.dot( _testAxis );\r\n\t\t\tvar p1 = v1.dot( _testAxis );\r\n\t\t\tvar p2 = v2.dot( _testAxis );\r\n\t\t\t// actual test, basically see if either of the most extreme of the triangle points intersects r\r\n\t\t\tif ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {\r\n\r\n\t\t\t\t// points of the projected triangle are outside the projected half-length of the aabb\r\n\t\t\t\t// the axis is seperating and we can exit\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\n\n\tvar _box$1 = new Box3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Sphere( center, radius ) {\r\n\r\n\t\tthis.center = ( center !== undefined ) ? center : new Vector3();\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Sphere.prototype, {\r\n\r\n\t\tset: function ( center, radius ) {\r\n\r\n\t\t\tthis.center.copy( center );\r\n\t\t\tthis.radius = radius;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points, optionalCenter ) {\r\n\r\n\t\t\tvar center = this.center;\r\n\r\n\t\t\tif ( optionalCenter !== undefined ) {\r\n\r\n\t\t\t\tcenter.copy( optionalCenter );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_box$1.setFromPoints( points ).getCenter( center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar maxRadiusSq = 0;\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.radius = Math.sqrt( maxRadiusSq );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( sphere ) {\r\n\r\n\t\t\tthis.center.copy( sphere.center );\r\n\t\t\tthis.radius = sphere.radius;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tempty: function () {\r\n\r\n\t\t\treturn ( this.radius <= 0 );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn ( point.distanceTo( this.center ) - this.radius );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\tvar radiusSum = this.radius + sphere.radius;\r\n\r\n\t\t\treturn sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsSphere( this );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\treturn Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tvar deltaLengthSq = this.center.distanceToSquared( point );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Sphere: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.copy( point );\r\n\r\n\t\t\tif ( deltaLengthSq > ( this.radius * this.radius ) ) {\r\n\r\n\t\t\t\ttarget.sub( this.center ).normalize();\r\n\t\t\t\ttarget.multiplyScalar( this.radius ).add( this.center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetBoundingBox: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );\r\n\t\t\t\ttarget = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.set( this.center, this.center );\r\n\t\t\ttarget.expandByScalar( this.radius );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\tthis.center.applyMatrix4( matrix );\r\n\t\t\tthis.radius = this.radius * matrix.getMaxScaleOnAxis();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.center.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( sphere ) {\r\n\r\n\t\t\treturn sphere.center.equals( this.center ) && ( sphere.radius === this.radius );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _vector$3 = new Vector3();\r\n\tvar _segCenter = new Vector3();\r\n\tvar _segDir = new Vector3();\r\n\tvar _diff = new Vector3();\r\n\r\n\tvar _edge1 = new Vector3();\r\n\tvar _edge2 = new Vector3();\r\n\tvar _normal = new Vector3();\r\n\r\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tfunction Ray( origin, direction ) {\r\n\r\n\t\tthis.origin = ( origin !== undefined ) ? origin : new Vector3();\r\n\t\tthis.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );\r\n\r\n\t}\r\n\r\n\tObject.assign( Ray.prototype, {\r\n\r\n\t\tset: function ( origin, direction ) {\r\n\r\n\t\t\tthis.origin.copy( origin );\r\n\t\t\tthis.direction.copy( direction );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( ray ) {\r\n\r\n\t\t\tthis.origin.copy( ray.origin );\r\n\t\t\tthis.direction.copy( ray.direction );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tat: function ( t, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Ray: .at() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.direction ).multiplyScalar( t ).add( this.origin );\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( v ) {\r\n\r\n\t\t\tthis.direction.copy( v ).sub( this.origin ).normalize();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trecast: function ( t ) {\r\n\r\n\t\t\tthis.origin.copy( this.at( t, _vector$3 ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.subVectors( point, this.origin );\r\n\r\n\t\t\tvar directionDistance = target.dot( this.direction );\r\n\r\n\t\t\tif ( directionDistance < 0 ) {\r\n\r\n\t\t\t\treturn target.copy( this.origin );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn Math.sqrt( this.distanceSqToPoint( point ) );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSqToPoint: function ( point ) {\r\n\r\n\t\t\tvar directionDistance = _vector$3.subVectors( point, this.origin ).dot( this.direction );\r\n\r\n\t\t\t// point behind the ray\r\n\r\n\t\t\tif ( directionDistance < 0 ) {\r\n\r\n\t\t\t\treturn this.origin.distanceToSquared( point );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vector$3.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\r\n\r\n\t\t\treturn _vector$3.distanceToSquared( point );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {\r\n\r\n\t\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h\r\n\t\t\t// It returns the min distance between the ray and the segment\r\n\t\t\t// defined by v0 and v1\r\n\t\t\t// It can also set two optional targets :\r\n\t\t\t// - The closest point on the ray\r\n\t\t\t// - The closest point on the segment\r\n\r\n\t\t\t_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );\r\n\t\t\t_segDir.copy( v1 ).sub( v0 ).normalize();\r\n\t\t\t_diff.copy( this.origin ).sub( _segCenter );\r\n\r\n\t\t\tvar segExtent = v0.distanceTo( v1 ) * 0.5;\r\n\t\t\tvar a01 = - this.direction.dot( _segDir );\r\n\t\t\tvar b0 = _diff.dot( this.direction );\r\n\t\t\tvar b1 = - _diff.dot( _segDir );\r\n\t\t\tvar c = _diff.lengthSq();\r\n\t\t\tvar det = Math.abs( 1 - a01 * a01 );\r\n\t\t\tvar s0, s1, sqrDist, extDet;\r\n\r\n\t\t\tif ( det > 0 ) {\r\n\r\n\t\t\t\t// The ray and segment are not parallel.\r\n\r\n\t\t\t\ts0 = a01 * b1 - b0;\r\n\t\t\t\ts1 = a01 * b0 - b1;\r\n\t\t\t\textDet = segExtent * det;\r\n\r\n\t\t\t\tif ( s0 >= 0 ) {\r\n\r\n\t\t\t\t\tif ( s1 >= - extDet ) {\r\n\r\n\t\t\t\t\t\tif ( s1 <= extDet ) {\r\n\r\n\t\t\t\t\t\t\t// region 0\r\n\t\t\t\t\t\t\t// Minimum at interior points of ray and segment.\r\n\r\n\t\t\t\t\t\t\tvar invDet = 1 / det;\r\n\t\t\t\t\t\t\ts0 *= invDet;\r\n\t\t\t\t\t\t\ts1 *= invDet;\r\n\t\t\t\t\t\t\tsqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t// region 1\r\n\r\n\t\t\t\t\t\t\ts1 = segExtent;\r\n\t\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// region 5\r\n\r\n\t\t\t\t\t\ts1 = - segExtent;\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tif ( s1 <= - extDet ) {\r\n\r\n\t\t\t\t\t\t// region 4\r\n\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );\r\n\t\t\t\t\t\ts1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t} else if ( s1 <= extDet ) {\r\n\r\n\t\t\t\t\t\t// region 3\r\n\r\n\t\t\t\t\t\ts0 = 0;\r\n\t\t\t\t\t\ts1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// region 2\r\n\r\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * segExtent + b0 ) );\r\n\t\t\t\t\t\ts1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\r\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Ray and segment are parallel.\r\n\r\n\t\t\t\ts1 = ( a01 > 0 ) ? - segExtent : segExtent;\r\n\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\r\n\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( optionalPointOnRay ) {\r\n\r\n\t\t\t\toptionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( optionalPointOnSegment ) {\r\n\r\n\t\t\t\toptionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn sqrDist;\r\n\r\n\t\t},\r\n\r\n\t\tintersectSphere: function ( sphere, target ) {\r\n\r\n\t\t\t_vector$3.subVectors( sphere.center, this.origin );\r\n\t\t\tvar tca = _vector$3.dot( this.direction );\r\n\t\t\tvar d2 = _vector$3.dot( _vector$3 ) - tca * tca;\r\n\t\t\tvar radius2 = sphere.radius * sphere.radius;\r\n\r\n\t\t\tif ( d2 > radius2 ) { return null; }\r\n\r\n\t\t\tvar thc = Math.sqrt( radius2 - d2 );\r\n\r\n\t\t\t// t0 = first intersect point - entrance on front of sphere\r\n\t\t\tvar t0 = tca - thc;\r\n\r\n\t\t\t// t1 = second intersect point - exit point on back of sphere\r\n\t\t\tvar t1 = tca + thc;\r\n\r\n\t\t\t// test to see if both t0 and t1 are behind the ray - if so, return null\r\n\t\t\tif ( t0 < 0 && t1 < 0 ) { return null; }\r\n\r\n\t\t\t// test to see if t0 is behind the ray:\r\n\t\t\t// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,\r\n\t\t\t// in order to always return an intersect point that is in front of the ray.\r\n\t\t\tif ( t0 < 0 ) { return this.at( t1, target ); }\r\n\r\n\t\t\t// else t0 is in front of the ray, so return the first collision point scaled by t0\r\n\t\t\treturn this.at( t0, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\treturn this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPlane: function ( plane ) {\r\n\r\n\t\t\tvar denominator = plane.normal.dot( this.direction );\r\n\r\n\t\t\tif ( denominator === 0 ) {\r\n\r\n\t\t\t\t// line is coplanar, return origin\r\n\t\t\t\tif ( plane.distanceToPoint( this.origin ) === 0 ) {\r\n\r\n\t\t\t\t\treturn 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Null is preferable to undefined since undefined means.... it is undefined\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;\r\n\r\n\t\t\t// Return if the ray never intersects the plane\r\n\r\n\t\t\treturn t >= 0 ? t : null;\r\n\r\n\t\t},\r\n\r\n\t\tintersectPlane: function ( plane, target ) {\r\n\r\n\t\t\tvar t = this.distanceToPlane( plane );\r\n\r\n\t\t\tif ( t === null ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.at( t, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsPlane: function ( plane ) {\r\n\r\n\t\t\t// check if the ray lies on the plane first\r\n\r\n\t\t\tvar distToPoint = plane.distanceToPoint( this.origin );\r\n\r\n\t\t\tif ( distToPoint === 0 ) {\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar denominator = plane.normal.dot( this.direction );\r\n\r\n\t\t\tif ( denominator * distToPoint < 0 ) {\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// ray origin is behind the plane (and is pointing behind it)\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t},\r\n\r\n\t\tintersectBox: function ( box, target ) {\r\n\r\n\t\t\tvar tmin, tmax, tymin, tymax, tzmin, tzmax;\r\n\r\n\t\t\tvar invdirx = 1 / this.direction.x,\r\n\t\t\t\tinvdiry = 1 / this.direction.y,\r\n\t\t\t\tinvdirz = 1 / this.direction.z;\r\n\r\n\t\t\tvar origin = this.origin;\r\n\r\n\t\t\tif ( invdirx >= 0 ) {\r\n\r\n\t\t\t\ttmin = ( box.min.x - origin.x ) * invdirx;\r\n\t\t\t\ttmax = ( box.max.x - origin.x ) * invdirx;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttmin = ( box.max.x - origin.x ) * invdirx;\r\n\t\t\t\ttmax = ( box.min.x - origin.x ) * invdirx;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( invdiry >= 0 ) {\r\n\r\n\t\t\t\ttymin = ( box.min.y - origin.y ) * invdiry;\r\n\t\t\t\ttymax = ( box.max.y - origin.y ) * invdiry;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttymin = ( box.max.y - origin.y ) * invdiry;\r\n\t\t\t\ttymax = ( box.min.y - origin.y ) * invdiry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( tmin > tymax ) || ( tymin > tmax ) ) { return null; }\r\n\r\n\t\t\t// These lines also handle the case where tmin or tmax is NaN\r\n\t\t\t// (result of 0 * Infinity). x !== x returns true if x is NaN\r\n\r\n\t\t\tif ( tymin > tmin || tmin !== tmin ) { tmin = tymin; }\r\n\r\n\t\t\tif ( tymax < tmax || tmax !== tmax ) { tmax = tymax; }\r\n\r\n\t\t\tif ( invdirz >= 0 ) {\r\n\r\n\t\t\t\ttzmin = ( box.min.z - origin.z ) * invdirz;\r\n\t\t\t\ttzmax = ( box.max.z - origin.z ) * invdirz;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttzmin = ( box.max.z - origin.z ) * invdirz;\r\n\t\t\t\ttzmax = ( box.min.z - origin.z ) * invdirz;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( tmin > tzmax ) || ( tzmin > tmax ) ) { return null; }\r\n\r\n\t\t\tif ( tzmin > tmin || tmin !== tmin ) { tmin = tzmin; }\r\n\r\n\t\t\tif ( tzmax < tmax || tmax !== tmax ) { tmax = tzmax; }\r\n\r\n\t\t\t//return point closest to the ray (positive side)\r\n\r\n\t\t\tif ( tmax < 0 ) { return null; }\r\n\r\n\t\t\treturn this.at( tmin >= 0 ? tmin : tmax, target );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn this.intersectBox( box, _vector$3 ) !== null;\r\n\r\n\t\t},\r\n\r\n\t\tintersectTriangle: function ( a, b, c, backfaceCulling, target ) {\r\n\r\n\t\t\t// Compute the offset origin, edges, and normal.\r\n\r\n\t\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h\r\n\r\n\t\t\t_edge1.subVectors( b, a );\r\n\t\t\t_edge2.subVectors( c, a );\r\n\t\t\t_normal.crossVectors( _edge1, _edge2 );\r\n\r\n\t\t\t// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,\r\n\t\t\t// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by\r\n\t\t\t// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))\r\n\t\t\t// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))\r\n\t\t\t// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)\r\n\t\t\tvar DdN = this.direction.dot( _normal );\r\n\t\t\tvar sign;\r\n\r\n\t\t\tif ( DdN > 0 ) {\r\n\r\n\t\t\t\tif ( backfaceCulling ) { return null; }\r\n\t\t\t\tsign = 1;\r\n\r\n\t\t\t} else if ( DdN < 0 ) {\r\n\r\n\t\t\t\tsign = - 1;\r\n\t\t\t\tDdN = - DdN;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_diff.subVectors( this.origin, a );\r\n\t\t\tvar DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );\r\n\r\n\t\t\t// b1 < 0, no intersection\r\n\t\t\tif ( DdQxE2 < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );\r\n\r\n\t\t\t// b2 < 0, no intersection\r\n\t\t\tif ( DdE1xQ < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// b1+b2 > 1, no intersection\r\n\t\t\tif ( DdQxE2 + DdE1xQ > DdN ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Line intersects triangle, check if ray does.\r\n\t\t\tvar QdN = - sign * _diff.dot( _normal );\r\n\r\n\t\t\t// t < 0, no intersection\r\n\t\t\tif ( QdN < 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Ray intersects triangle.\r\n\t\t\treturn this.at( QdN / DdN, target );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix4 ) {\r\n\r\n\t\t\tthis.origin.applyMatrix4( matrix4 );\r\n\t\t\tthis.direction.transformDirection( matrix4 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( ray ) {\r\n\r\n\t\t\treturn ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _vector1 = new Vector3();\r\n\tvar _vector2 = new Vector3();\r\n\tvar _normalMatrix = new Matrix3();\r\n\r\n\tfunction Plane( normal, constant ) {\r\n\r\n\t\t// normal is assumed to be normalized\r\n\r\n\t\tthis.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );\r\n\t\tthis.constant = ( constant !== undefined ) ? constant : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Plane.prototype, {\r\n\r\n\t\tisPlane: true,\r\n\r\n\t\tset: function ( normal, constant ) {\r\n\r\n\t\t\tthis.normal.copy( normal );\r\n\t\t\tthis.constant = constant;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetComponents: function ( x, y, z, w ) {\r\n\r\n\t\t\tthis.normal.set( x, y, z );\r\n\t\t\tthis.constant = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromNormalAndCoplanarPoint: function ( normal, point ) {\r\n\r\n\t\t\tthis.normal.copy( normal );\r\n\t\t\tthis.constant = - point.dot( this.normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCoplanarPoints: function ( a, b, c ) {\r\n\r\n\t\t\tvar normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();\r\n\r\n\t\t\t// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?\r\n\r\n\t\t\tthis.setFromNormalAndCoplanarPoint( normal, a );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( plane ) {\r\n\r\n\t\t\tthis.normal.copy( plane.normal );\r\n\t\t\tthis.constant = plane.constant;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\t// Note: will lead to a divide by zero if the plane is invalid.\r\n\r\n\t\t\tvar inverseNormalLength = 1.0 / this.normal.length();\r\n\t\t\tthis.normal.multiplyScalar( inverseNormalLength );\r\n\t\t\tthis.constant *= inverseNormalLength;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnegate: function () {\r\n\r\n\t\t\tthis.constant *= - 1;\r\n\t\t\tthis.normal.negate();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\treturn this.normal.dot( point ) + this.constant;\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToSphere: function ( sphere ) {\r\n\r\n\t\t\treturn this.distanceToPoint( sphere.center ) - sphere.radius;\r\n\r\n\t\t},\r\n\r\n\t\tprojectPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .projectPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );\r\n\r\n\t\t},\r\n\r\n\t\tintersectLine: function ( line, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .intersectLine() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar direction = line.delta( _vector1 );\r\n\r\n\t\t\tvar denominator = this.normal.dot( direction );\r\n\r\n\t\t\tif ( denominator === 0 ) {\r\n\r\n\t\t\t\t// line is coplanar, return origin\r\n\t\t\t\tif ( this.distanceToPoint( line.start ) === 0 ) {\r\n\r\n\t\t\t\t\treturn target.copy( line.start );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Unsure if this is the correct method to handle this case.\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;\r\n\r\n\t\t\tif ( t < 0 || t > 1 ) {\r\n\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( direction ).multiplyScalar( t ).add( line.start );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsLine: function ( line ) {\r\n\r\n\t\t\t// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.\r\n\r\n\t\t\tvar startSign = this.distanceToPoint( line.start );\r\n\t\t\tvar endSign = this.distanceToPoint( line.end );\r\n\r\n\t\t\treturn ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsPlane( this );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\treturn sphere.intersectsPlane( this );\r\n\r\n\t\t},\r\n\r\n\t\tcoplanarPoint: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Plane: .coplanarPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( this.normal ).multiplyScalar( - this.constant );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix, optionalNormalMatrix ) {\r\n\r\n\t\t\tvar normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );\r\n\r\n\t\t\tvar referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );\r\n\r\n\t\t\tvar normal = this.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\tthis.constant = - referencePoint.dot( normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.constant -= offset.dot( this.normal );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( plane ) {\r\n\r\n\t\t\treturn plane.normal.equals( this.normal ) && ( plane.constant === this.constant );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _v0$1 = new Vector3();\r\n\tvar _v1$3 = new Vector3();\r\n\tvar _v2$1 = new Vector3();\r\n\tvar _v3 = new Vector3();\r\n\r\n\tvar _vab = new Vector3();\r\n\tvar _vac = new Vector3();\r\n\tvar _vbc = new Vector3();\r\n\tvar _vap = new Vector3();\r\n\tvar _vbp = new Vector3();\r\n\tvar _vcp = new Vector3();\r\n\r\n\tfunction Triangle( a, b, c ) {\r\n\r\n\t\tthis.a = ( a !== undefined ) ? a : new Vector3();\r\n\t\tthis.b = ( b !== undefined ) ? b : new Vector3();\r\n\t\tthis.c = ( c !== undefined ) ? c : new Vector3();\r\n\r\n\t}\r\n\r\n\tObject.assign( Triangle, {\r\n\r\n\t\tgetNormal: function ( a, b, c, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getNormal() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.subVectors( c, b );\r\n\t\t\t_v0$1.subVectors( a, b );\r\n\t\t\ttarget.cross( _v0$1 );\r\n\r\n\t\t\tvar targetLengthSq = target.lengthSq();\r\n\t\t\tif ( targetLengthSq > 0 ) {\r\n\r\n\t\t\t\treturn target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( 0, 0, 0 );\r\n\r\n\t\t},\r\n\r\n\t\t// static/instance method to calculate barycentric coordinates\r\n\t\t// based on: http://www.blackpawn.com/texts/pointinpoly/default.html\r\n\t\tgetBarycoord: function ( point, a, b, c, target ) {\r\n\r\n\t\t\t_v0$1.subVectors( c, a );\r\n\t\t\t_v1$3.subVectors( b, a );\r\n\t\t\t_v2$1.subVectors( point, a );\r\n\r\n\t\t\tvar dot00 = _v0$1.dot( _v0$1 );\r\n\t\t\tvar dot01 = _v0$1.dot( _v1$3 );\r\n\t\t\tvar dot02 = _v0$1.dot( _v2$1 );\r\n\t\t\tvar dot11 = _v1$3.dot( _v1$3 );\r\n\t\t\tvar dot12 = _v1$3.dot( _v2$1 );\r\n\r\n\t\t\tvar denom = ( dot00 * dot11 - dot01 * dot01 );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getBarycoord() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// collinear or singular triangle\r\n\t\t\tif ( denom === 0 ) {\r\n\r\n\t\t\t\t// arbitrary location outside of triangle?\r\n\t\t\t\t// not sure if this is the best idea, maybe should be returning undefined\r\n\t\t\t\treturn target.set( - 2, - 1, - 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar invDenom = 1 / denom;\r\n\t\t\tvar u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;\r\n\t\t\tvar v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;\r\n\r\n\t\t\t// barycentric coordinates must always sum to 1\r\n\t\t\treturn target.set( 1 - u - v, v, u );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point, a, b, c ) {\r\n\r\n\t\t\tTriangle.getBarycoord( point, a, b, c, _v3 );\r\n\r\n\t\t\treturn ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );\r\n\r\n\t\t},\r\n\r\n\t\tgetUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {\r\n\r\n\t\t\tthis.getBarycoord( point, p1, p2, p3, _v3 );\r\n\r\n\t\t\ttarget.set( 0, 0 );\r\n\t\t\ttarget.addScaledVector( uv1, _v3.x );\r\n\t\t\ttarget.addScaledVector( uv2, _v3.y );\r\n\t\t\ttarget.addScaledVector( uv3, _v3.z );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tisFrontFacing: function ( a, b, c, direction ) {\r\n\r\n\t\t\t_v0$1.subVectors( c, b );\r\n\t\t\t_v1$3.subVectors( a, b );\r\n\r\n\t\t\t// strictly front facing\r\n\t\t\treturn ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle.prototype, {\r\n\r\n\t\tset: function ( a, b, c ) {\r\n\r\n\t\t\tthis.a.copy( a );\r\n\t\t\tthis.b.copy( b );\r\n\t\t\tthis.c.copy( c );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPointsAndIndices: function ( points, i0, i1, i2 ) {\r\n\r\n\t\t\tthis.a.copy( points[ i0 ] );\r\n\t\t\tthis.b.copy( points[ i1 ] );\r\n\t\t\tthis.c.copy( points[ i2 ] );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( triangle ) {\r\n\r\n\t\t\tthis.a.copy( triangle.a );\r\n\t\t\tthis.b.copy( triangle.b );\r\n\t\t\tthis.c.copy( triangle.c );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetArea: function () {\r\n\r\n\t\t\t_v0$1.subVectors( this.c, this.b );\r\n\t\t\t_v1$3.subVectors( this.a, this.b );\r\n\r\n\t\t\treturn _v0$1.cross( _v1$3 ).length() * 0.5;\r\n\r\n\t\t},\r\n\r\n\t\tgetMidpoint: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getMidpoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );\r\n\r\n\t\t},\r\n\r\n\t\tgetNormal: function ( target ) {\r\n\r\n\t\t\treturn Triangle.getNormal( this.a, this.b, this.c, target );\r\n\r\n\t\t},\r\n\r\n\t\tgetPlane: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .getPlane() target is now required' );\r\n\t\t\t\ttarget = new Plane();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.setFromCoplanarPoints( this.a, this.b, this.c );\r\n\r\n\t\t},\r\n\r\n\t\tgetBarycoord: function ( point, target ) {\r\n\r\n\t\t\treturn Triangle.getBarycoord( point, this.a, this.b, this.c, target );\r\n\r\n\t\t},\r\n\r\n\t\tgetUV: function ( point, uv1, uv2, uv3, target ) {\r\n\r\n\t\t\treturn Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn Triangle.containsPoint( point, this.a, this.b, this.c );\r\n\r\n\t\t},\r\n\r\n\t\tisFrontFacing: function ( direction ) {\r\n\r\n\t\t\treturn Triangle.isFrontFacing( this.a, this.b, this.c, direction );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\treturn box.intersectsTriangle( this );\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( p, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar a = this.a, b = this.b, c = this.c;\r\n\t\t\tvar v, w;\r\n\r\n\t\t\t// algorithm thanks to Real-Time Collision Detection by Christer Ericson,\r\n\t\t\t// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,\r\n\t\t\t// under the accompanying license; see chapter 5.1.5 for detailed explanation.\r\n\t\t\t// basically, we're distinguishing which of the voronoi regions of the triangle\r\n\t\t\t// the point lies in with the minimum amount of redundant computation.\r\n\r\n\t\t\t_vab.subVectors( b, a );\r\n\t\t\t_vac.subVectors( c, a );\r\n\t\t\t_vap.subVectors( p, a );\r\n\t\t\tvar d1 = _vab.dot( _vap );\r\n\t\t\tvar d2 = _vac.dot( _vap );\r\n\t\t\tif ( d1 <= 0 && d2 <= 0 ) {\r\n\r\n\t\t\t\t// vertex region of A; barycentric coords (1, 0, 0)\r\n\t\t\t\treturn target.copy( a );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vbp.subVectors( p, b );\r\n\t\t\tvar d3 = _vab.dot( _vbp );\r\n\t\t\tvar d4 = _vac.dot( _vbp );\r\n\t\t\tif ( d3 >= 0 && d4 <= d3 ) {\r\n\r\n\t\t\t\t// vertex region of B; barycentric coords (0, 1, 0)\r\n\t\t\t\treturn target.copy( b );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vc = d1 * d4 - d3 * d2;\r\n\t\t\tif ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {\r\n\r\n\t\t\t\tv = d1 / ( d1 - d3 );\r\n\t\t\t\t// edge region of AB; barycentric coords (1-v, v, 0)\r\n\t\t\t\treturn target.copy( a ).addScaledVector( _vab, v );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vcp.subVectors( p, c );\r\n\t\t\tvar d5 = _vab.dot( _vcp );\r\n\t\t\tvar d6 = _vac.dot( _vcp );\r\n\t\t\tif ( d6 >= 0 && d5 <= d6 ) {\r\n\r\n\t\t\t\t// vertex region of C; barycentric coords (0, 0, 1)\r\n\t\t\t\treturn target.copy( c );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vb = d5 * d2 - d1 * d6;\r\n\t\t\tif ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {\r\n\r\n\t\t\t\tw = d2 / ( d2 - d6 );\r\n\t\t\t\t// edge region of AC; barycentric coords (1-w, 0, w)\r\n\t\t\t\treturn target.copy( a ).addScaledVector( _vac, w );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar va = d3 * d6 - d5 * d4;\r\n\t\t\tif ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {\r\n\r\n\t\t\t\t_vbc.subVectors( c, b );\r\n\t\t\t\tw = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );\r\n\t\t\t\t// edge region of BC; barycentric coords (0, 1-w, w)\r\n\t\t\t\treturn target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// face region\r\n\t\t\tvar denom = 1 / ( va + vb + vc );\r\n\t\t\t// u = va * denom\r\n\t\t\tv = vb * denom;\r\n\t\t\tw = vc * denom;\r\n\r\n\t\t\treturn target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( triangle ) {\r\n\r\n\t\t\treturn triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,\r\n\t\t'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,\r\n\t\t'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,\r\n\t\t'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,\r\n\t\t'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,\r\n\t\t'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,\r\n\t\t'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,\r\n\t\t'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,\r\n\t\t'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,\r\n\t\t'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,\r\n\t\t'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,\r\n\t\t'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,\r\n\t\t'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,\r\n\t\t'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,\r\n\t\t'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,\r\n\t\t'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,\r\n\t\t'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,\r\n\t\t'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,\r\n\t\t'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,\r\n\t\t'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,\r\n\t\t'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,\r\n\t\t'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,\r\n\t\t'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,\r\n\t\t'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };\r\n\r\n\tvar _hslA = { h: 0, s: 0, l: 0 };\r\n\tvar _hslB = { h: 0, s: 0, l: 0 };\r\n\r\n\tfunction Color( r, g, b ) {\r\n\r\n\t\tif ( g === undefined && b === undefined ) {\r\n\r\n\t\t\t// r is THREE.Color, hex or string\r\n\t\t\treturn this.set( r );\r\n\r\n\t\t}\r\n\r\n\t\treturn this.setRGB( r, g, b );\r\n\r\n\t}\r\n\r\n\tfunction hue2rgb( p, q, t ) {\r\n\r\n\t\tif ( t < 0 ) { t += 1; }\r\n\t\tif ( t > 1 ) { t -= 1; }\r\n\t\tif ( t < 1 / 6 ) { return p + ( q - p ) * 6 * t; }\r\n\t\tif ( t < 1 / 2 ) { return q; }\r\n\t\tif ( t < 2 / 3 ) { return p + ( q - p ) * 6 * ( 2 / 3 - t ); }\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\tfunction SRGBToLinear( c ) {\r\n\r\n\t\treturn ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );\r\n\r\n\t}\r\n\r\n\tfunction LinearToSRGB( c ) {\r\n\r\n\t\treturn ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;\r\n\r\n\t}\r\n\r\n\tObject.assign( Color.prototype, {\r\n\r\n\t\tisColor: true,\r\n\r\n\t\tr: 1, g: 1, b: 1,\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value && value.isColor ) {\r\n\r\n\t\t\t\tthis.copy( value );\r\n\r\n\t\t\t} else if ( typeof value === 'number' ) {\r\n\r\n\t\t\t\tthis.setHex( value );\r\n\r\n\t\t\t} else if ( typeof value === 'string' ) {\r\n\r\n\t\t\t\tthis.setStyle( value );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.r = scalar;\r\n\t\t\tthis.g = scalar;\r\n\t\t\tthis.b = scalar;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetHex: function ( hex ) {\r\n\r\n\t\t\thex = Math.floor( hex );\r\n\r\n\t\t\tthis.r = ( hex >> 16 & 255 ) / 255;\r\n\t\t\tthis.g = ( hex >> 8 & 255 ) / 255;\r\n\t\t\tthis.b = ( hex & 255 ) / 255;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRGB: function ( r, g, b ) {\r\n\r\n\t\t\tthis.r = r;\r\n\t\t\tthis.g = g;\r\n\t\t\tthis.b = b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetHSL: function ( h, s, l ) {\r\n\r\n\t\t\t// h,s,l ranges are in 0.0 - 1.0\r\n\t\t\th = _Math.euclideanModulo( h, 1 );\r\n\t\t\ts = _Math.clamp( s, 0, 1 );\r\n\t\t\tl = _Math.clamp( l, 0, 1 );\r\n\r\n\t\t\tif ( s === 0 ) {\r\n\r\n\t\t\t\tthis.r = this.g = this.b = l;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );\r\n\t\t\t\tvar q = ( 2 * l ) - p;\r\n\r\n\t\t\t\tthis.r = hue2rgb( q, p, h + 1 / 3 );\r\n\t\t\t\tthis.g = hue2rgb( q, p, h );\r\n\t\t\t\tthis.b = hue2rgb( q, p, h - 1 / 3 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetStyle: function ( style ) {\r\n\r\n\t\t\tfunction handleAlpha( string ) {\r\n\r\n\t\t\t\tif ( string === undefined ) { return; }\r\n\r\n\t\t\t\tif ( parseFloat( string ) < 1 ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar m;\r\n\r\n\t\t\tif ( m = /^((?:rgb|hsl)a?)\\(\\s*([^\\)]*)\\)/.exec( style ) ) {\r\n\r\n\t\t\t\t// rgb / hsl\r\n\r\n\t\t\t\tvar color;\r\n\t\t\t\tvar name = m[ 1 ];\r\n\t\t\t\tvar components = m[ 2 ];\r\n\r\n\t\t\t\tswitch ( name ) {\r\n\r\n\t\t\t\t\tcase 'rgb':\r\n\t\t\t\t\tcase 'rgba':\r\n\r\n\t\t\t\t\t\tif ( color = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// rgb(255,0,0) rgba(255,0,0,0.5)\r\n\t\t\t\t\t\t\tthis.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;\r\n\t\t\t\t\t\t\tthis.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;\r\n\t\t\t\t\t\t\tthis.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( color = /^(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)\r\n\t\t\t\t\t\t\tthis.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;\r\n\t\t\t\t\t\t\tthis.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;\r\n\t\t\t\t\t\t\tthis.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'hsl':\r\n\t\t\t\t\tcase 'hsla':\r\n\r\n\t\t\t\t\t\tif ( color = /^([0-9]*\\.?[0-9]+)\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\r\n\r\n\t\t\t\t\t\t\t// hsl(120,50%,50%) hsla(120,50%,50%,0.5)\r\n\t\t\t\t\t\t\tvar h = parseFloat( color[ 1 ] ) / 360;\r\n\t\t\t\t\t\t\tvar s = parseInt( color[ 2 ], 10 ) / 100;\r\n\t\t\t\t\t\t\tvar l = parseInt( color[ 3 ], 10 ) / 100;\r\n\r\n\t\t\t\t\t\t\thandleAlpha( color[ 5 ] );\r\n\r\n\t\t\t\t\t\t\treturn this.setHSL( h, s, l );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( m = /^\\#([A-Fa-f0-9]+)$/.exec( style ) ) {\r\n\r\n\t\t\t\t// hex color\r\n\r\n\t\t\t\tvar hex = m[ 1 ];\r\n\t\t\t\tvar size = hex.length;\r\n\r\n\t\t\t\tif ( size === 3 ) {\r\n\r\n\t\t\t\t\t// #ff0\r\n\t\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;\r\n\t\t\t\t\tthis.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;\r\n\t\t\t\t\tthis.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t} else if ( size === 6 ) {\r\n\r\n\t\t\t\t\t// #ff0000\r\n\t\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;\r\n\t\t\t\t\tthis.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;\r\n\t\t\t\t\tthis.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;\r\n\r\n\t\t\t\t\treturn this;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( style && style.length > 0 ) {\r\n\r\n\t\t\t\treturn this.setColorName( style );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetColorName: function ( style ) {\r\n\r\n\t\t\t// color keywords\r\n\t\t\tvar hex = _colorKeywords[ style ];\r\n\r\n\t\t\tif ( hex !== undefined ) {\r\n\r\n\t\t\t\t// red\r\n\t\t\t\tthis.setHex( hex );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// unknown color\r\n\t\t\t\tconsole.warn( 'THREE.Color: Unknown color ' + style );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.r, this.g, this.b );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( color ) {\r\n\r\n\t\t\tthis.r = color.r;\r\n\t\t\tthis.g = color.g;\r\n\t\t\tthis.b = color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyGammaToLinear: function ( color, gammaFactor ) {\r\n\r\n\t\t\tif ( gammaFactor === undefined ) { gammaFactor = 2.0; }\r\n\r\n\t\t\tthis.r = Math.pow( color.r, gammaFactor );\r\n\t\t\tthis.g = Math.pow( color.g, gammaFactor );\r\n\t\t\tthis.b = Math.pow( color.b, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyLinearToGamma: function ( color, gammaFactor ) {\r\n\r\n\t\t\tif ( gammaFactor === undefined ) { gammaFactor = 2.0; }\r\n\r\n\t\t\tvar safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;\r\n\r\n\t\t\tthis.r = Math.pow( color.r, safeInverse );\r\n\t\t\tthis.g = Math.pow( color.g, safeInverse );\r\n\t\t\tthis.b = Math.pow( color.b, safeInverse );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertGammaToLinear: function ( gammaFactor ) {\r\n\r\n\t\t\tthis.copyGammaToLinear( this, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertLinearToGamma: function ( gammaFactor ) {\r\n\r\n\t\t\tthis.copyLinearToGamma( this, gammaFactor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopySRGBToLinear: function ( color ) {\r\n\r\n\t\t\tthis.r = SRGBToLinear( color.r );\r\n\t\t\tthis.g = SRGBToLinear( color.g );\r\n\t\t\tthis.b = SRGBToLinear( color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyLinearToSRGB: function ( color ) {\r\n\r\n\t\t\tthis.r = LinearToSRGB( color.r );\r\n\t\t\tthis.g = LinearToSRGB( color.g );\r\n\t\t\tthis.b = LinearToSRGB( color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertSRGBToLinear: function () {\r\n\r\n\t\t\tthis.copySRGBToLinear( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconvertLinearToSRGB: function () {\r\n\r\n\t\t\tthis.copyLinearToSRGB( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetHex: function () {\r\n\r\n\t\t\treturn ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;\r\n\r\n\t\t},\r\n\r\n\t\tgetHexString: function () {\r\n\r\n\t\t\treturn ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );\r\n\r\n\t\t},\r\n\r\n\t\tgetHSL: function ( target ) {\r\n\r\n\t\t\t// h,s,l ranges are in 0.0 - 1.0\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Color: .getHSL() target is now required' );\r\n\t\t\t\ttarget = { h: 0, s: 0, l: 0 };\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar r = this.r, g = this.g, b = this.b;\r\n\r\n\t\t\tvar max = Math.max( r, g, b );\r\n\t\t\tvar min = Math.min( r, g, b );\r\n\r\n\t\t\tvar hue, saturation;\r\n\t\t\tvar lightness = ( min + max ) / 2.0;\r\n\r\n\t\t\tif ( min === max ) {\r\n\r\n\t\t\t\thue = 0;\r\n\t\t\t\tsaturation = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar delta = max - min;\r\n\r\n\t\t\t\tsaturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );\r\n\r\n\t\t\t\tswitch ( max ) {\r\n\r\n\t\t\t\t\tcase r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;\r\n\t\t\t\t\tcase g: hue = ( b - r ) / delta + 2; break;\r\n\t\t\t\t\tcase b: hue = ( r - g ) / delta + 4; break;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\thue /= 6;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttarget.h = hue;\r\n\t\t\ttarget.s = saturation;\r\n\t\t\ttarget.l = lightness;\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tgetStyle: function () {\r\n\r\n\t\t\treturn 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';\r\n\r\n\t\t},\r\n\r\n\t\toffsetHSL: function ( h, s, l ) {\r\n\r\n\t\t\tthis.getHSL( _hslA );\r\n\r\n\t\t\t_hslA.h += h; _hslA.s += s; _hslA.l += l;\r\n\r\n\t\t\tthis.setHSL( _hslA.h, _hslA.s, _hslA.l );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( color ) {\r\n\r\n\t\t\tthis.r += color.r;\r\n\t\t\tthis.g += color.g;\r\n\t\t\tthis.b += color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddColors: function ( color1, color2 ) {\r\n\r\n\t\t\tthis.r = color1.r + color2.r;\r\n\t\t\tthis.g = color1.g + color2.g;\r\n\t\t\tthis.b = color1.b + color2.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddScalar: function ( s ) {\r\n\r\n\t\t\tthis.r += s;\r\n\t\t\tthis.g += s;\r\n\t\t\tthis.b += s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsub: function ( color ) {\r\n\r\n\t\t\tthis.r = Math.max( 0, this.r - color.r );\r\n\t\t\tthis.g = Math.max( 0, this.g - color.g );\r\n\t\t\tthis.b = Math.max( 0, this.b - color.b );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiply: function ( color ) {\r\n\r\n\t\t\tthis.r *= color.r;\r\n\t\t\tthis.g *= color.g;\r\n\t\t\tthis.b *= color.b;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmultiplyScalar: function ( s ) {\r\n\r\n\t\t\tthis.r *= s;\r\n\t\t\tthis.g *= s;\r\n\t\t\tthis.b *= s;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( color, alpha ) {\r\n\r\n\t\t\tthis.r += ( color.r - this.r ) * alpha;\r\n\t\t\tthis.g += ( color.g - this.g ) * alpha;\r\n\t\t\tthis.b += ( color.b - this.b ) * alpha;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerpHSL: function ( color, alpha ) {\r\n\r\n\t\t\tthis.getHSL( _hslA );\r\n\t\t\tcolor.getHSL( _hslB );\r\n\r\n\t\t\tvar h = _Math.lerp( _hslA.h, _hslB.h, alpha );\r\n\t\t\tvar s = _Math.lerp( _hslA.s, _hslB.s, alpha );\r\n\t\t\tvar l = _Math.lerp( _hslA.l, _hslB.l, alpha );\r\n\r\n\t\t\tthis.setHSL( h, s, l );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( c ) {\r\n\r\n\t\t\treturn ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.r = array[ offset ];\r\n\t\t\tthis.g = array[ offset + 1 ];\r\n\t\t\tthis.b = array[ offset + 2 ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tarray[ offset ] = this.r;\r\n\t\t\tarray[ offset + 1 ] = this.g;\r\n\t\t\tarray[ offset + 2 ] = this.b;\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\treturn this.getHex();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tColor.NAMES = _colorKeywords;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Face3( a, b, c, normal, color, materialIndex ) {\r\n\r\n\t\tthis.a = a;\r\n\t\tthis.b = b;\r\n\t\tthis.c = c;\r\n\r\n\t\tthis.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();\r\n\t\tthis.vertexNormals = Array.isArray( normal ) ? normal : [];\r\n\r\n\t\tthis.color = ( color && color.isColor ) ? color : new Color();\r\n\t\tthis.vertexColors = Array.isArray( color ) ? color : [];\r\n\r\n\t\tthis.materialIndex = materialIndex !== undefined ? materialIndex : 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( Face3.prototype, {\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.a = source.a;\r\n\t\t\tthis.b = source.b;\r\n\t\t\tthis.c = source.c;\r\n\r\n\t\t\tthis.normal.copy( source.normal );\r\n\t\t\tthis.color.copy( source.color );\r\n\r\n\t\t\tthis.materialIndex = source.materialIndex;\r\n\r\n\t\t\tfor ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertexNormals[ i ] = source.vertexNormals[ i ].clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertexColors[ i ] = source.vertexColors[ i ].clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar materialId = 0;\r\n\r\n\tfunction Material() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: materialId ++ } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Material';\r\n\r\n\t\tthis.fog = true;\r\n\r\n\t\tthis.blending = NormalBlending;\r\n\t\tthis.side = FrontSide;\r\n\t\tthis.flatShading = false;\r\n\t\tthis.vertexTangents = false;\r\n\t\tthis.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors\r\n\r\n\t\tthis.opacity = 1;\r\n\t\tthis.transparent = false;\r\n\r\n\t\tthis.blendSrc = SrcAlphaFactor;\r\n\t\tthis.blendDst = OneMinusSrcAlphaFactor;\r\n\t\tthis.blendEquation = AddEquation;\r\n\t\tthis.blendSrcAlpha = null;\r\n\t\tthis.blendDstAlpha = null;\r\n\t\tthis.blendEquationAlpha = null;\r\n\r\n\t\tthis.depthFunc = LessEqualDepth;\r\n\t\tthis.depthTest = true;\r\n\t\tthis.depthWrite = true;\r\n\r\n\t\tthis.stencilWriteMask = 0xff;\r\n\t\tthis.stencilFunc = AlwaysStencilFunc;\r\n\t\tthis.stencilRef = 0;\r\n\t\tthis.stencilFuncMask = 0xff;\r\n\t\tthis.stencilFail = KeepStencilOp;\r\n\t\tthis.stencilZFail = KeepStencilOp;\r\n\t\tthis.stencilZPass = KeepStencilOp;\r\n\t\tthis.stencilWrite = false;\r\n\r\n\t\tthis.clippingPlanes = null;\r\n\t\tthis.clipIntersection = false;\r\n\t\tthis.clipShadows = false;\r\n\r\n\t\tthis.shadowSide = null;\r\n\r\n\t\tthis.colorWrite = true;\r\n\r\n\t\tthis.precision = null; // override the renderer's default precision for this material\r\n\r\n\t\tthis.polygonOffset = false;\r\n\t\tthis.polygonOffsetFactor = 0;\r\n\t\tthis.polygonOffsetUnits = 0;\r\n\r\n\t\tthis.dithering = false;\r\n\r\n\t\tthis.alphaTest = 0;\r\n\t\tthis.premultipliedAlpha = false;\r\n\r\n\t\tthis.visible = true;\r\n\r\n\t\tthis.toneMapped = true;\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tMaterial.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Material,\r\n\r\n\t\tisMaterial: true,\r\n\r\n\t\tonBeforeCompile: function () {},\r\n\r\n\t\tsetValues: function ( values ) {\r\n\r\n\t\t\tif ( values === undefined ) { return; }\r\n\r\n\t\t\tfor ( var key in values ) {\r\n\r\n\t\t\t\tvar newValue = values[ key ];\r\n\r\n\t\t\t\tif ( newValue === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.Material: '\" + key + \"' parameter is undefined.\" );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// for backward compatability if shading is set in the constructor\r\n\t\t\t\tif ( key === 'shading' ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\t\t\t\t\tthis.flatShading = ( newValue === FlatShading ) ? true : false;\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar currentValue = this[ key ];\r\n\r\n\t\t\t\tif ( currentValue === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.\" + this.type + \": '\" + key + \"' is not a property of this material.\" );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( currentValue && currentValue.isColor ) {\r\n\r\n\t\t\t\t\tcurrentValue.set( newValue );\r\n\r\n\t\t\t\t} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {\r\n\r\n\t\t\t\t\tcurrentValue.copy( newValue );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis[ key ] = newValue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar isRoot = ( meta === undefined || typeof meta === 'string' );\r\n\r\n\t\t\tif ( isRoot ) {\r\n\r\n\t\t\t\tmeta = {\r\n\t\t\t\t\ttextures: {},\r\n\t\t\t\t\timages: {}\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Material',\r\n\t\t\t\t\tgenerator: 'Material.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard Material serialization\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\r\n\t\t\tif ( this.color && this.color.isColor ) { data.color = this.color.getHex(); }\r\n\r\n\t\t\tif ( this.roughness !== undefined ) { data.roughness = this.roughness; }\r\n\t\t\tif ( this.metalness !== undefined ) { data.metalness = this.metalness; }\r\n\r\n\t\t\tif ( this.sheen && this.sheen.isColor ) { data.sheen = this.sheen.getHex(); }\r\n\t\t\tif ( this.emissive && this.emissive.isColor ) { data.emissive = this.emissive.getHex(); }\r\n\t\t\tif ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) { data.emissiveIntensity = this.emissiveIntensity; }\r\n\r\n\t\t\tif ( this.specular && this.specular.isColor ) { data.specular = this.specular.getHex(); }\r\n\t\t\tif ( this.shininess !== undefined ) { data.shininess = this.shininess; }\r\n\t\t\tif ( this.clearcoat !== undefined ) { data.clearcoat = this.clearcoat; }\r\n\t\t\tif ( this.clearcoatRoughness !== undefined ) { data.clearcoatRoughness = this.clearcoatRoughness; }\r\n\r\n\t\t\tif ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {\r\n\r\n\t\t\t\tdata.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.clearcoatNormalScale = this.clearcoatNormalScale.toArray();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.map && this.map.isTexture ) { data.map = this.map.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.matcap && this.matcap.isTexture ) { data.matcap = this.matcap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.alphaMap && this.alphaMap.isTexture ) { data.alphaMap = this.alphaMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.lightMap && this.lightMap.isTexture ) { data.lightMap = this.lightMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.aoMap && this.aoMap.isTexture ) {\r\n\r\n\t\t\t\tdata.aoMap = this.aoMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.aoMapIntensity = this.aoMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.bumpMap && this.bumpMap.isTexture ) {\r\n\r\n\t\t\t\tdata.bumpMap = this.bumpMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.bumpScale = this.bumpScale;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.normalMap && this.normalMap.isTexture ) {\r\n\r\n\t\t\t\tdata.normalMap = this.normalMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.normalMapType = this.normalMapType;\r\n\t\t\t\tdata.normalScale = this.normalScale.toArray();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.displacementMap && this.displacementMap.isTexture ) {\r\n\r\n\t\t\t\tdata.displacementMap = this.displacementMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.displacementScale = this.displacementScale;\r\n\t\t\t\tdata.displacementBias = this.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.roughnessMap && this.roughnessMap.isTexture ) { data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.metalnessMap && this.metalnessMap.isTexture ) { data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.emissiveMap && this.emissiveMap.isTexture ) { data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; }\r\n\t\t\tif ( this.specularMap && this.specularMap.isTexture ) { data.specularMap = this.specularMap.toJSON( meta ).uuid; }\r\n\r\n\t\t\tif ( this.envMap && this.envMap.isTexture ) {\r\n\r\n\t\t\t\tdata.envMap = this.envMap.toJSON( meta ).uuid;\r\n\t\t\t\tdata.reflectivity = this.reflectivity; // Scale behind envMap\r\n\t\t\t\tdata.refractionRatio = this.refractionRatio;\r\n\r\n\t\t\t\tif ( this.combine !== undefined ) { data.combine = this.combine; }\r\n\t\t\t\tif ( this.envMapIntensity !== undefined ) { data.envMapIntensity = this.envMapIntensity; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.gradientMap && this.gradientMap.isTexture ) {\r\n\r\n\t\t\t\tdata.gradientMap = this.gradientMap.toJSON( meta ).uuid;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.size !== undefined ) { data.size = this.size; }\r\n\t\t\tif ( this.sizeAttenuation !== undefined ) { data.sizeAttenuation = this.sizeAttenuation; }\r\n\r\n\t\t\tif ( this.blending !== NormalBlending ) { data.blending = this.blending; }\r\n\t\t\tif ( this.flatShading === true ) { data.flatShading = this.flatShading; }\r\n\t\t\tif ( this.side !== FrontSide ) { data.side = this.side; }\r\n\t\t\tif ( this.vertexColors !== NoColors ) { data.vertexColors = this.vertexColors; }\r\n\r\n\t\t\tif ( this.opacity < 1 ) { data.opacity = this.opacity; }\r\n\t\t\tif ( this.transparent === true ) { data.transparent = this.transparent; }\r\n\r\n\t\t\tdata.depthFunc = this.depthFunc;\r\n\t\t\tdata.depthTest = this.depthTest;\r\n\t\t\tdata.depthWrite = this.depthWrite;\r\n\r\n\t\t\tdata.stencilWrite = this.stencilWrite;\r\n\t\t\tdata.stencilWriteMask = this.stencilWriteMask;\r\n\t\t\tdata.stencilFunc = this.stencilFunc;\r\n\t\t\tdata.stencilRef = this.stencilRef;\r\n\t\t\tdata.stencilFuncMask = this.stencilFuncMask;\r\n\t\t\tdata.stencilFail = this.stencilFail;\r\n\t\t\tdata.stencilZFail = this.stencilZFail;\r\n\t\t\tdata.stencilZPass = this.stencilZPass;\r\n\r\n\t\t\t// rotation (SpriteMaterial)\r\n\t\t\tif ( this.rotation && this.rotation !== 0 ) { data.rotation = this.rotation; }\r\n\r\n\t\t\tif ( this.polygonOffset === true ) { data.polygonOffset = true; }\r\n\t\t\tif ( this.polygonOffsetFactor !== 0 ) { data.polygonOffsetFactor = this.polygonOffsetFactor; }\r\n\t\t\tif ( this.polygonOffsetUnits !== 0 ) { data.polygonOffsetUnits = this.polygonOffsetUnits; }\r\n\r\n\t\t\tif ( this.linewidth && this.linewidth !== 1 ) { data.linewidth = this.linewidth; }\r\n\t\t\tif ( this.dashSize !== undefined ) { data.dashSize = this.dashSize; }\r\n\t\t\tif ( this.gapSize !== undefined ) { data.gapSize = this.gapSize; }\r\n\t\t\tif ( this.scale !== undefined ) { data.scale = this.scale; }\r\n\r\n\t\t\tif ( this.dithering === true ) { data.dithering = true; }\r\n\r\n\t\t\tif ( this.alphaTest > 0 ) { data.alphaTest = this.alphaTest; }\r\n\t\t\tif ( this.premultipliedAlpha === true ) { data.premultipliedAlpha = this.premultipliedAlpha; }\r\n\r\n\t\t\tif ( this.wireframe === true ) { data.wireframe = this.wireframe; }\r\n\t\t\tif ( this.wireframeLinewidth > 1 ) { data.wireframeLinewidth = this.wireframeLinewidth; }\r\n\t\t\tif ( this.wireframeLinecap !== 'round' ) { data.wireframeLinecap = this.wireframeLinecap; }\r\n\t\t\tif ( this.wireframeLinejoin !== 'round' ) { data.wireframeLinejoin = this.wireframeLinejoin; }\r\n\r\n\t\t\tif ( this.morphTargets === true ) { data.morphTargets = true; }\r\n\t\t\tif ( this.morphNormals === true ) { data.morphNormals = true; }\r\n\t\t\tif ( this.skinning === true ) { data.skinning = true; }\r\n\r\n\t\t\tif ( this.visible === false ) { data.visible = false; }\r\n\r\n\t\t\tif ( this.toneMapped === false ) { data.toneMapped = false; }\r\n\r\n\t\t\tif ( JSON.stringify( this.userData ) !== '{}' ) { data.userData = this.userData; }\r\n\r\n\t\t\t// TODO: Copied from Object3D.toJSON\r\n\r\n\t\t\tfunction extractFromCache( cache ) {\r\n\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\tfor ( var key in cache ) {\r\n\r\n\t\t\t\t\tvar data = cache[ key ];\r\n\t\t\t\t\tdelete data.metadata;\r\n\t\t\t\t\tvalues.push( data );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn values;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isRoot ) {\r\n\r\n\t\t\t\tvar textures = extractFromCache( meta.textures );\r\n\t\t\t\tvar images = extractFromCache( meta.images );\r\n\r\n\t\t\t\tif ( textures.length > 0 ) { data.textures = textures; }\r\n\t\t\t\tif ( images.length > 0 ) { data.images = images; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\tthis.fog = source.fog;\r\n\r\n\t\t\tthis.blending = source.blending;\r\n\t\t\tthis.side = source.side;\r\n\t\t\tthis.flatShading = source.flatShading;\r\n\t\t\tthis.vertexTangents = source.vertexTangents;\r\n\t\t\tthis.vertexColors = source.vertexColors;\r\n\r\n\t\t\tthis.opacity = source.opacity;\r\n\t\t\tthis.transparent = source.transparent;\r\n\r\n\t\t\tthis.blendSrc = source.blendSrc;\r\n\t\t\tthis.blendDst = source.blendDst;\r\n\t\t\tthis.blendEquation = source.blendEquation;\r\n\t\t\tthis.blendSrcAlpha = source.blendSrcAlpha;\r\n\t\t\tthis.blendDstAlpha = source.blendDstAlpha;\r\n\t\t\tthis.blendEquationAlpha = source.blendEquationAlpha;\r\n\r\n\t\t\tthis.depthFunc = source.depthFunc;\r\n\t\t\tthis.depthTest = source.depthTest;\r\n\t\t\tthis.depthWrite = source.depthWrite;\r\n\r\n\t\t\tthis.stencilWriteMask = source.stencilWriteMask;\r\n\t\t\tthis.stencilFunc = source.stencilFunc;\r\n\t\t\tthis.stencilRef = source.stencilRef;\r\n\t\t\tthis.stencilFuncMask = source.stencilFuncMask;\r\n\t\t\tthis.stencilFail = source.stencilFail;\r\n\t\t\tthis.stencilZFail = source.stencilZFail;\r\n\t\t\tthis.stencilZPass = source.stencilZPass;\r\n\t\t\tthis.stencilWrite = source.stencilWrite;\r\n\r\n\t\t\tvar srcPlanes = source.clippingPlanes,\r\n\t\t\t\tdstPlanes = null;\r\n\r\n\t\t\tif ( srcPlanes !== null ) {\r\n\r\n\t\t\t\tvar n = srcPlanes.length;\r\n\t\t\t\tdstPlanes = new Array( n );\r\n\r\n\t\t\t\tfor ( var i = 0; i !== n; ++ i )\r\n\t\t\t\t\t{ dstPlanes[ i ] = srcPlanes[ i ].clone(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.clippingPlanes = dstPlanes;\r\n\t\t\tthis.clipIntersection = source.clipIntersection;\r\n\t\t\tthis.clipShadows = source.clipShadows;\r\n\r\n\t\t\tthis.shadowSide = source.shadowSide;\r\n\r\n\t\t\tthis.colorWrite = source.colorWrite;\r\n\r\n\t\t\tthis.precision = source.precision;\r\n\r\n\t\t\tthis.polygonOffset = source.polygonOffset;\r\n\t\t\tthis.polygonOffsetFactor = source.polygonOffsetFactor;\r\n\t\t\tthis.polygonOffsetUnits = source.polygonOffsetUnits;\r\n\r\n\t\t\tthis.dithering = source.dithering;\r\n\r\n\t\t\tthis.alphaTest = source.alphaTest;\r\n\t\t\tthis.premultipliedAlpha = source.premultipliedAlpha;\r\n\r\n\t\t\tthis.visible = source.visible;\r\n\r\n\t\t\tthis.toneMapped = source.toneMapped;\r\n\r\n\t\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Material.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.Multiply,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * depthTest: ,\r\n\t * depthWrite: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshBasicMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshBasicMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // emissive\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshBasicMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshBasicMaterial.prototype.constructor = MeshBasicMaterial;\r\n\r\n\tMeshBasicMaterial.prototype.isMeshBasicMaterial = true;\r\n\r\n\tMeshBasicMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _vector$4 = new Vector3();\r\n\r\n\tfunction BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tif ( Array.isArray( array ) ) {\r\n\r\n\t\t\tthrow new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );\r\n\r\n\t\t}\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.array = array;\r\n\t\tthis.itemSize = itemSize;\r\n\t\tthis.count = array !== undefined ? array.length / itemSize : 0;\r\n\t\tthis.normalized = normalized === true;\r\n\r\n\t\tthis.usage = StaticDrawUsage;\r\n\t\tthis.updateRange = { offset: 0, count: - 1 };\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperty( BufferAttribute.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( BufferAttribute.prototype, {\r\n\r\n\t\tisBufferAttribute: true,\r\n\r\n\t\tonUploadCallback: function () {},\r\n\r\n\t\tsetUsage: function ( value ) {\r\n\r\n\t\t\tthis.usage = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.name = source.name;\r\n\t\t\tthis.array = new source.array.constructor( source.array );\r\n\t\t\tthis.itemSize = source.itemSize;\r\n\t\t\tthis.count = source.count;\r\n\t\t\tthis.normalized = source.normalized;\r\n\r\n\t\t\tthis.usage = source.usage;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyAt: function ( index1, attribute, index2 ) {\r\n\r\n\t\t\tindex1 *= this.itemSize;\r\n\t\t\tindex2 *= attribute.itemSize;\r\n\r\n\t\t\tfor ( var i = 0, l = this.itemSize; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyArray: function ( array ) {\r\n\r\n\t\t\tthis.array.set( array );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyColorsArray: function ( colors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = colors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar color = colors[ i ];\r\n\r\n\t\t\t\tif ( color === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );\r\n\t\t\t\t\tcolor = new Color();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = color.r;\r\n\t\t\t\tarray[ offset ++ ] = color.g;\r\n\t\t\t\tarray[ offset ++ ] = color.b;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector2sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector2();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector3sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector3();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\t\t\t\tarray[ offset ++ ] = vector.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyVector4sArray: function ( vectors ) {\r\n\r\n\t\t\tvar array = this.array, offset = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vector = vectors[ i ];\r\n\r\n\t\t\t\tif ( vector === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );\r\n\t\t\t\t\tvector = new Vector4();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tarray[ offset ++ ] = vector.x;\r\n\t\t\t\tarray[ offset ++ ] = vector.y;\r\n\t\t\t\tarray[ offset ++ ] = vector.z;\r\n\t\t\t\tarray[ offset ++ ] = vector.w;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix3: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyMatrix3( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyMatrix4( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tapplyNormalMatrix: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.applyNormalMatrix( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttransformDirection: function ( m ) {\r\n\r\n\t\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t_vector$4.x = this.getX( i );\r\n\t\t\t\t_vector$4.y = this.getY( i );\r\n\t\t\t\t_vector$4.z = this.getZ( i );\r\n\r\n\t\t\t\t_vector$4.transformDirection( m );\r\n\r\n\t\t\t\tthis.setXYZ( i, _vector$4.x, _vector$4.y, _vector$4.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.array.set( value, offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetX: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize ];\r\n\r\n\t\t},\r\n\r\n\t\tsetX: function ( index, x ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize ] = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetY: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 1 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( index, y ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetZ: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 2 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( index, z ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetW: function ( index ) {\r\n\r\n\t\t\treturn this.array[ index * this.itemSize + 3 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( index, w ) {\r\n\r\n\t\t\tthis.array[ index * this.itemSize + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXY: function ( index, x, y ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZ: function ( index, x, y, z ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\t\t\tthis.array[ index + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZW: function ( index, x, y, z, w ) {\r\n\r\n\t\t\tindex *= this.itemSize;\r\n\r\n\t\t\tthis.array[ index + 0 ] = x;\r\n\t\t\tthis.array[ index + 1 ] = y;\r\n\t\t\tthis.array[ index + 2 ] = z;\r\n\t\t\tthis.array[ index + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tonUpload: function ( callback ) {\r\n\r\n\t\t\tthis.onUploadCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.array, this.itemSize ).copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\treturn {\r\n\t\t\t\titemSize: this.itemSize,\r\n\t\t\t\ttype: this.array.constructor.name,\r\n\t\t\t\tarray: Array.prototype.slice.call( this.array ),\r\n\t\t\t\tnormalized: this.normalized\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction Int8BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt8BufferAttribute.prototype.constructor = Int8BufferAttribute;\r\n\r\n\r\n\tfunction Uint8BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;\r\n\r\n\r\n\tfunction Uint8ClampedBufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;\r\n\r\n\r\n\tfunction Int16BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt16BufferAttribute.prototype.constructor = Int16BufferAttribute;\r\n\r\n\r\n\tfunction Uint16BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;\r\n\r\n\r\n\tfunction Int32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tInt32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tInt32BufferAttribute.prototype.constructor = Int32BufferAttribute;\r\n\r\n\r\n\tfunction Uint32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tUint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tUint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;\r\n\r\n\r\n\tfunction Float32BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tFloat32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tFloat32BufferAttribute.prototype.constructor = Float32BufferAttribute;\r\n\r\n\r\n\tfunction Float64BufferAttribute( array, itemSize, normalized ) {\r\n\r\n\t\tBufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );\r\n\r\n\t}\r\n\r\n\tFloat64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\r\n\tFloat64BufferAttribute.prototype.constructor = Float64BufferAttribute;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction DirectGeometry() {\r\n\r\n\t\tthis.vertices = [];\r\n\t\tthis.normals = [];\r\n\t\tthis.colors = [];\r\n\t\tthis.uvs = [];\r\n\t\tthis.uvs2 = [];\r\n\r\n\t\tthis.groups = [];\r\n\r\n\t\tthis.morphTargets = {};\r\n\r\n\t\tthis.skinWeights = [];\r\n\t\tthis.skinIndices = [];\r\n\r\n\t\t// this.lineDistances = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\t// update flags\r\n\r\n\t\tthis.verticesNeedUpdate = false;\r\n\t\tthis.normalsNeedUpdate = false;\r\n\t\tthis.colorsNeedUpdate = false;\r\n\t\tthis.uvsNeedUpdate = false;\r\n\t\tthis.groupsNeedUpdate = false;\r\n\r\n\t}\r\n\r\n\tObject.assign( DirectGeometry.prototype, {\r\n\r\n\t\tcomputeGroups: function ( geometry ) {\r\n\r\n\t\t\tvar group;\r\n\t\t\tvar groups = [];\r\n\t\t\tvar materialIndex = undefined;\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\r\n\t\t\tfor ( var i = 0; i < faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\t// materials\r\n\r\n\t\t\t\tif ( face.materialIndex !== materialIndex ) {\r\n\r\n\t\t\t\t\tmaterialIndex = face.materialIndex;\r\n\r\n\t\t\t\t\tif ( group !== undefined ) {\r\n\r\n\t\t\t\t\t\tgroup.count = ( i * 3 ) - group.start;\r\n\t\t\t\t\t\tgroups.push( group );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgroup = {\r\n\t\t\t\t\t\tstart: i * 3,\r\n\t\t\t\t\t\tmaterialIndex: materialIndex\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( group !== undefined ) {\r\n\r\n\t\t\t\tgroup.count = ( i * 3 ) - group.start;\r\n\t\t\t\tgroups.push( group );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.groups = groups;\r\n\r\n\t\t},\r\n\r\n\t\tfromGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\t\t\tvar vertices = geometry.vertices;\r\n\t\t\tvar faceVertexUvs = geometry.faceVertexUvs;\r\n\r\n\t\t\tvar hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;\r\n\t\t\tvar hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;\r\n\r\n\t\t\t// morphs\r\n\r\n\t\t\tvar morphTargets = geometry.morphTargets;\r\n\t\t\tvar morphTargetsLength = morphTargets.length;\r\n\r\n\t\t\tvar morphTargetsPosition;\r\n\r\n\t\t\tif ( morphTargetsLength > 0 ) {\r\n\r\n\t\t\t\tmorphTargetsPosition = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < morphTargetsLength; i ++ ) {\r\n\r\n\t\t\t\t\tmorphTargetsPosition[ i ] = {\r\n\t\t\t\t\t\tname: morphTargets[ i ].name,\r\n\t\t\t\t\t \tdata: []\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.position = morphTargetsPosition;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphNormals = geometry.morphNormals;\r\n\t\t\tvar morphNormalsLength = morphNormals.length;\r\n\r\n\t\t\tvar morphTargetsNormal;\r\n\r\n\t\t\tif ( morphNormalsLength > 0 ) {\r\n\r\n\t\t\t\tmorphTargetsNormal = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < morphNormalsLength; i ++ ) {\r\n\r\n\t\t\t\t\tmorphTargetsNormal[ i ] = {\r\n\t\t\t\t\t\tname: morphNormals[ i ].name,\r\n\t\t\t\t\t \tdata: []\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.normal = morphTargetsNormal;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skins\r\n\r\n\t\t\tvar skinIndices = geometry.skinIndices;\r\n\t\t\tvar skinWeights = geometry.skinWeights;\r\n\r\n\t\t\tvar hasSkinIndices = skinIndices.length === vertices.length;\r\n\t\t\tvar hasSkinWeights = skinWeights.length === vertices.length;\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( vertices.length > 0 && faces.length === 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tthis.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tthis.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvar normal = face.normal;\r\n\r\n\t\t\t\t\tthis.normals.push( normal, normal, normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar vertexColors = face.vertexColors;\r\n\r\n\t\t\t\tif ( vertexColors.length === 3 ) {\r\n\r\n\t\t\t\t\tthis.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvar color = face.color;\r\n\r\n\t\t\t\t\tthis.colors.push( color, color, color );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexUv === true ) {\r\n\r\n\t\t\t\t\tvar vertexUvs = faceVertexUvs[ 0 ][ i ];\r\n\r\n\t\t\t\t\tif ( vertexUvs !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );\r\n\r\n\t\t\t\t\t\tthis.uvs.push( new Vector2(), new Vector2(), new Vector2() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexUv2 === true ) {\r\n\r\n\t\t\t\t\tvar vertexUvs = faceVertexUvs[ 1 ][ i ];\r\n\r\n\t\t\t\t\tif ( vertexUvs !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );\r\n\r\n\t\t\t\t\t\tthis.uvs2.push( new Vector2(), new Vector2(), new Vector2() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// morphs\r\n\r\n\t\t\t\tfor ( var j = 0; j < morphTargetsLength; j ++ ) {\r\n\r\n\t\t\t\t\tvar morphTarget = morphTargets[ j ].vertices;\r\n\r\n\t\t\t\t\tmorphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var j = 0; j < morphNormalsLength; j ++ ) {\r\n\r\n\t\t\t\t\tvar morphNormal = morphNormals[ j ].vertexNormals[ i ];\r\n\r\n\t\t\t\t\tmorphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// skins\r\n\r\n\t\t\t\tif ( hasSkinIndices ) {\r\n\r\n\t\t\t\t\tthis.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasSkinWeights ) {\r\n\r\n\t\t\t\t\tthis.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.computeGroups( geometry );\r\n\r\n\t\t\tthis.verticesNeedUpdate = geometry.verticesNeedUpdate;\r\n\t\t\tthis.normalsNeedUpdate = geometry.normalsNeedUpdate;\r\n\t\t\tthis.colorsNeedUpdate = geometry.colorsNeedUpdate;\r\n\t\t\tthis.uvsNeedUpdate = geometry.uvsNeedUpdate;\r\n\t\t\tthis.groupsNeedUpdate = geometry.groupsNeedUpdate;\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction arrayMax( array ) {\r\n\r\n\t\tif ( array.length === 0 ) { return - Infinity; }\r\n\r\n\t\tvar max = array[ 0 ];\r\n\r\n\t\tfor ( var i = 1, l = array.length; i < l; ++ i ) {\r\n\r\n\t\t\tif ( array[ i ] > max ) { max = array[ i ]; }\r\n\r\n\t\t}\r\n\r\n\t\treturn max;\r\n\r\n\t}\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id\r\n\r\n\tvar _m1$2 = new Matrix4();\r\n\tvar _obj = new Object3D();\r\n\tvar _offset = new Vector3();\r\n\tvar _box$2 = new Box3();\r\n\tvar _boxMorphTargets = new Box3();\r\n\tvar _vector$5 = new Vector3();\r\n\r\n\tfunction BufferGeometry() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'BufferGeometry';\r\n\r\n\t\tthis.index = null;\r\n\t\tthis.attributes = {};\r\n\r\n\t\tthis.morphAttributes = {};\r\n\t\tthis.morphTargetsRelative = false;\r\n\r\n\t\tthis.groups = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\tthis.drawRange = { start: 0, count: Infinity };\r\n\r\n\t\tthis.userData = {};\r\n\r\n\t}\r\n\r\n\tBufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: BufferGeometry,\r\n\r\n\t\tisBufferGeometry: true,\r\n\r\n\t\tgetIndex: function () {\r\n\r\n\t\t\treturn this.index;\r\n\r\n\t\t},\r\n\r\n\t\tsetIndex: function ( index ) {\r\n\r\n\t\t\tif ( Array.isArray( index ) ) {\r\n\r\n\t\t\t\tthis.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.index = index;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tgetAttribute: function ( name ) {\r\n\r\n\t\t\treturn this.attributes[ name ];\r\n\r\n\t\t},\r\n\r\n\t\tsetAttribute: function ( name, attribute ) {\r\n\r\n\t\t\tthis.attributes[ name ] = attribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdeleteAttribute: function ( name ) {\r\n\r\n\t\t\tdelete this.attributes[ name ];\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddGroup: function ( start, count, materialIndex ) {\r\n\r\n\t\t\tthis.groups.push( {\r\n\r\n\t\t\t\tstart: start,\r\n\t\t\t\tcount: count,\r\n\t\t\t\tmaterialIndex: materialIndex !== undefined ? materialIndex : 0\r\n\r\n\t\t\t} );\r\n\r\n\t\t},\r\n\r\n\t\tclearGroups: function () {\r\n\r\n\t\t\tthis.groups = [];\r\n\r\n\t\t},\r\n\r\n\t\tsetDrawRange: function ( start, count ) {\r\n\r\n\t\t\tthis.drawRange.start = start;\r\n\t\t\tthis.drawRange.count = count;\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\r\n\t\t\tif ( position !== undefined ) {\r\n\r\n\t\t\t\tmatrix.applyToBufferAttribute( position );\r\n\t\t\t\tposition.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar normal = this.attributes.normal;\r\n\r\n\t\t\tif ( normal !== undefined ) {\r\n\r\n\t\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\t\tnormal.applyNormalMatrix( normalMatrix );\r\n\r\n\t\t\t\tnormal.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar tangent = this.attributes.tangent;\r\n\r\n\t\t\tif ( tangent !== undefined ) {\r\n\r\n\t\t\t\ttangent.transformDirection( matrix );\r\n\r\n\t\t\t\ttangent.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world x-axis\r\n\r\n\t\t\t_m1$2.makeRotationX( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world y-axis\r\n\r\n\t\t\t_m1$2.makeRotationY( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world z-axis\r\n\r\n\t\t\t_m1$2.makeRotationZ( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( x, y, z ) {\r\n\r\n\t\t\t// translate geometry\r\n\r\n\t\t\t_m1$2.makeTranslation( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( x, y, z ) {\r\n\r\n\t\t\t// scale geometry\r\n\r\n\t\t\t_m1$2.makeScale( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$2 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( vector ) {\r\n\r\n\t\t\t_obj.lookAt( vector );\r\n\r\n\t\t\t_obj.updateMatrix();\r\n\r\n\t\t\tthis.applyMatrix( _obj.matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function () {\r\n\r\n\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\tthis.boundingBox.getCenter( _offset ).negate();\r\n\r\n\t\t\tthis.translate( _offset.x, _offset.y, _offset.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromObject: function ( object ) {\r\n\r\n\t\t\t// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( object.isPoints || object.isLine ) {\r\n\r\n\t\t\t\tvar positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );\r\n\t\t\t\tvar colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );\r\n\r\n\t\t\t\tthis.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );\r\n\t\t\t\tthis.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );\r\n\r\n\t\t\t\tif ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {\r\n\r\n\t\t\t\t\tvar lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );\r\n\r\n\t\t\t\t\tthis.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isMesh ) {\r\n\r\n\t\t\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\t\t\tthis.fromGeometry( geometry );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tvar position = [];\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tposition.push( point.x, point.y, point.z || 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateFromObject: function ( object ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( object.isMesh ) {\r\n\r\n\t\t\t\tvar direct = geometry.__directGeometry;\r\n\r\n\t\t\t\tif ( geometry.elementsNeedUpdate === true ) {\r\n\r\n\t\t\t\t\tdirect = undefined;\r\n\t\t\t\t\tgeometry.elementsNeedUpdate = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( direct === undefined ) {\r\n\r\n\t\t\t\t\treturn this.fromGeometry( geometry );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdirect.verticesNeedUpdate = geometry.verticesNeedUpdate;\r\n\t\t\t\tdirect.normalsNeedUpdate = geometry.normalsNeedUpdate;\r\n\t\t\t\tdirect.colorsNeedUpdate = geometry.colorsNeedUpdate;\r\n\t\t\t\tdirect.uvsNeedUpdate = geometry.uvsNeedUpdate;\r\n\t\t\t\tdirect.groupsNeedUpdate = geometry.groupsNeedUpdate;\r\n\r\n\t\t\t\tgeometry.verticesNeedUpdate = false;\r\n\t\t\t\tgeometry.normalsNeedUpdate = false;\r\n\t\t\t\tgeometry.colorsNeedUpdate = false;\r\n\t\t\t\tgeometry.uvsNeedUpdate = false;\r\n\t\t\t\tgeometry.groupsNeedUpdate = false;\r\n\r\n\t\t\t\tgeometry = direct;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute;\r\n\r\n\t\t\tif ( geometry.verticesNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.position;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector3sArray( geometry.vertices );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.verticesNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.normalsNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.normal;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector3sArray( geometry.normals );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.normalsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.colorsNeedUpdate === true ) {\r\n\r\n\t\t\t\tattribute = this.attributes.color;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyColorsArray( geometry.colors );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.colorsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvsNeedUpdate ) {\r\n\r\n\t\t\t\tattribute = this.attributes.uv;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyVector2sArray( geometry.uvs );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.uvsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.lineDistancesNeedUpdate ) {\r\n\r\n\t\t\t\tattribute = this.attributes.lineDistance;\r\n\r\n\t\t\t\tif ( attribute !== undefined ) {\r\n\r\n\t\t\t\t\tattribute.copyArray( geometry.lineDistances );\r\n\t\t\t\t\tattribute.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.lineDistancesNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.groupsNeedUpdate ) {\r\n\r\n\t\t\t\tgeometry.computeGroups( object.geometry );\r\n\t\t\t\tthis.groups = geometry.groups;\r\n\r\n\t\t\t\tgeometry.groupsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tfromGeometry: function ( geometry ) {\r\n\r\n\t\t\tgeometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );\r\n\r\n\t\t\treturn this.fromDirectGeometry( geometry.__directGeometry );\r\n\r\n\t\t},\r\n\r\n\t\tfromDirectGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar positions = new Float32Array( geometry.vertices.length * 3 );\r\n\t\t\tthis.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );\r\n\r\n\t\t\tif ( geometry.normals.length > 0 ) {\r\n\r\n\t\t\t\tvar normals = new Float32Array( geometry.normals.length * 3 );\r\n\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.colors.length > 0 ) {\r\n\r\n\t\t\t\tvar colors = new Float32Array( geometry.colors.length * 3 );\r\n\t\t\t\tthis.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvs.length > 0 ) {\r\n\r\n\t\t\t\tvar uvs = new Float32Array( geometry.uvs.length * 2 );\r\n\t\t\t\tthis.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.uvs2.length > 0 ) {\r\n\r\n\t\t\t\tvar uvs2 = new Float32Array( geometry.uvs2.length * 2 );\r\n\t\t\t\tthis.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tthis.groups = geometry.groups;\r\n\r\n\t\t\t// morphs\r\n\r\n\t\t\tfor ( var name in geometry.morphTargets ) {\r\n\r\n\t\t\t\tvar array = [];\r\n\t\t\t\tvar morphTargets = geometry.morphTargets[ name ];\r\n\r\n\t\t\t\tfor ( var i = 0, l = morphTargets.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar morphTarget = morphTargets[ i ];\r\n\r\n\t\t\t\t\tvar attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );\r\n\t\t\t\t\tattribute.name = morphTarget.name;\r\n\r\n\t\t\t\t\tarray.push( attribute.copyVector3sArray( morphTarget.data ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphAttributes[ name ] = array;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skinning\r\n\r\n\t\t\tif ( geometry.skinIndices.length > 0 ) {\r\n\r\n\t\t\t\tvar skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );\r\n\t\t\t\tthis.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.skinWeights.length > 0 ) {\r\n\r\n\t\t\t\tvar skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );\r\n\t\t\t\tthis.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingBox: function () {\r\n\r\n\t\t\tif ( this.boundingBox === null ) {\r\n\r\n\t\t\t\tthis.boundingBox = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\t\t\tvar morphAttributesPosition = this.morphAttributes.position;\r\n\r\n\t\t\tif ( position !== undefined ) {\r\n\r\n\t\t\t\tthis.boundingBox.setFromBufferAttribute( position );\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\t_box$2.setFromBufferAttribute( morphAttribute );\r\n\r\n\t\t\t\t\t\tif ( this.morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( this.boundingBox.min, _box$2.min );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( this.boundingBox.max, _box$2.max );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box$2.min );\r\n\t\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box$2.max );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.boundingBox.makeEmpty();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The \"position\" attribute is likely to have NaN values.', this );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingSphere: function () {\r\n\r\n\t\t\tif ( this.boundingSphere === null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = new Sphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar position = this.attributes.position;\r\n\t\t\tvar morphAttributesPosition = this.morphAttributes.position;\r\n\r\n\t\t\tif ( position ) {\r\n\r\n\t\t\t\t// first, find the center of the bounding sphere\r\n\r\n\t\t\t\tvar center = this.boundingSphere.center;\r\n\r\n\t\t\t\t_box$2.setFromBufferAttribute( position );\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\t_boxMorphTargets.setFromBufferAttribute( morphAttribute );\r\n\r\n\t\t\t\t\t\tif ( this.morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( _box$2.min, _boxMorphTargets.min );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t\t_vector$5.addVectors( _box$2.max, _boxMorphTargets.max );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _vector$5 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _boxMorphTargets.min );\r\n\t\t\t\t\t\t\t_box$2.expandByPoint( _boxMorphTargets.max );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_box$2.getCenter( center );\r\n\r\n\t\t\t\t// second, try to find a boundingSphere with a radius smaller than the\r\n\t\t\t\t// boundingSphere of the boundingBox: sqrt(3) smaller in the best case\r\n\r\n\t\t\t\tvar maxRadiusSq = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, il = position.count; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t_vector$5.fromBufferAttribute( position, i );\r\n\r\n\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$5 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// process morph attributes if present\r\n\r\n\t\t\t\tif ( morphAttributesPosition ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\r\n\t\t\t\t\t\tvar morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t_vector$5.fromBufferAttribute( morphAttribute, j );\r\n\r\n\t\t\t\t\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t\t\t\t_offset.fromBufferAttribute( position, j );\r\n\t\t\t\t\t\t\t\t_vector$5.add( _offset );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$5 ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.boundingSphere.radius = Math.sqrt( maxRadiusSq );\r\n\r\n\t\t\t\tif ( isNaN( this.boundingSphere.radius ) ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The \"position\" attribute is likely to have NaN values.', this );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFaceNormals: function () {\r\n\r\n\t\t\t// backwards compatibility\r\n\r\n\t\t},\r\n\r\n\t\tcomputeVertexNormals: function () {\r\n\r\n\t\t\tvar index = this.index;\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tif ( attributes.position ) {\r\n\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( attributes.normal === undefined ) {\r\n\r\n\t\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// reset existing normals to zero\r\n\r\n\t\t\t\t\tvar array = attributes.normal.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tarray[ i ] = 0;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar normals = attributes.normal.array;\r\n\r\n\t\t\t\tvar vA, vB, vC;\r\n\t\t\t\tvar pA = new Vector3(), pB = new Vector3(), pC = new Vector3();\r\n\t\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\t\t// indexed elements\r\n\r\n\t\t\t\tif ( index ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = index.count; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\tvA = indices[ i + 0 ] * 3;\r\n\t\t\t\t\t\tvB = indices[ i + 1 ] * 3;\r\n\t\t\t\t\t\tvC = indices[ i + 2 ] * 3;\r\n\r\n\t\t\t\t\t\tpA.fromArray( positions, vA );\r\n\t\t\t\t\t\tpB.fromArray( positions, vB );\r\n\t\t\t\t\t\tpC.fromArray( positions, vC );\r\n\r\n\t\t\t\t\t\tcb.subVectors( pC, pB );\r\n\t\t\t\t\t\tab.subVectors( pA, pB );\r\n\t\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\t\tnormals[ vA ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vA + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vA + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ vB ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vB + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vB + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ vC ] += cb.x;\r\n\t\t\t\t\t\tnormals[ vC + 1 ] += cb.y;\r\n\t\t\t\t\t\tnormals[ vC + 2 ] += cb.z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// non-indexed elements (unconnected triangle soup)\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = positions.length; i < il; i += 9 ) {\r\n\r\n\t\t\t\t\t\tpA.fromArray( positions, i );\r\n\t\t\t\t\t\tpB.fromArray( positions, i + 3 );\r\n\t\t\t\t\t\tpC.fromArray( positions, i + 6 );\r\n\r\n\t\t\t\t\t\tcb.subVectors( pC, pB );\r\n\t\t\t\t\t\tab.subVectors( pA, pB );\r\n\t\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\t\tnormals[ i ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 1 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 2 ] = cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ i + 3 ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 4 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 5 ] = cb.z;\r\n\r\n\t\t\t\t\t\tnormals[ i + 6 ] = cb.x;\r\n\t\t\t\t\t\tnormals[ i + 7 ] = cb.y;\r\n\t\t\t\t\t\tnormals[ i + 8 ] = cb.z;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.normalizeNormals();\r\n\r\n\t\t\t\tattributes.normal.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tmerge: function ( geometry, offset ) {\r\n\r\n\t\t\tif ( ! ( geometry && geometry.isBufferGeometry ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( offset === undefined ) {\r\n\r\n\t\t\t\toffset = 0;\r\n\r\n\t\t\t\tconsole.warn(\r\n\t\t\t\t\t'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '\r\n\t\t\t\t\t+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'\r\n\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tif ( geometry.attributes[ key ] === undefined ) { continue; }\r\n\r\n\t\t\t\tvar attribute1 = attributes[ key ];\r\n\t\t\t\tvar attributeArray1 = attribute1.array;\r\n\r\n\t\t\t\tvar attribute2 = geometry.attributes[ key ];\r\n\t\t\t\tvar attributeArray2 = attribute2.array;\r\n\r\n\t\t\t\tvar attributeOffset = attribute2.itemSize * offset;\r\n\t\t\t\tvar length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );\r\n\r\n\t\t\t\tfor ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {\r\n\r\n\t\t\t\t\tattributeArray1[ j ] = attributeArray2[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalizeNormals: function () {\r\n\r\n\t\t\tvar normals = this.attributes.normal;\r\n\r\n\t\t\tfor ( var i = 0, il = normals.count; i < il; i ++ ) {\r\n\r\n\t\t\t\t_vector$5.x = normals.getX( i );\r\n\t\t\t\t_vector$5.y = normals.getY( i );\r\n\t\t\t\t_vector$5.z = normals.getZ( i );\r\n\r\n\t\t\t\t_vector$5.normalize();\r\n\r\n\t\t\t\tnormals.setXYZ( i, _vector$5.x, _vector$5.y, _vector$5.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoNonIndexed: function () {\r\n\r\n\t\t\tfunction convertBufferAttribute( attribute, indices ) {\r\n\r\n\t\t\t\tvar array = attribute.array;\r\n\t\t\t\tvar itemSize = attribute.itemSize;\r\n\r\n\t\t\t\tvar array2 = new array.constructor( indices.length * itemSize );\r\n\r\n\t\t\t\tvar index = 0, index2 = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, l = indices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tindex = indices[ i ] * itemSize;\r\n\r\n\t\t\t\t\tfor ( var j = 0; j < itemSize; j ++ ) {\r\n\r\n\t\t\t\t\t\tarray2[ index2 ++ ] = array[ index ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn new BufferAttribute( array2, itemSize );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.index === null ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar geometry2 = new BufferGeometry();\r\n\r\n\t\t\tvar indices = this.index.array;\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\t// attributes\r\n\r\n\t\t\tfor ( var name in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ name ];\r\n\r\n\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\r\n\r\n\t\t\t\tgeometry2.setAttribute( name, newAttribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph attributes\r\n\r\n\t\t\tvar morphAttributes = this.morphAttributes;\r\n\r\n\t\t\tfor ( name in morphAttributes ) {\r\n\r\n\t\t\t\tvar morphArray = [];\r\n\t\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\r\n\r\n\t\t\t\tfor ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar attribute = morphAttribute[ i ];\r\n\r\n\t\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\r\n\r\n\t\t\t\t\tmorphArray.push( newAttribute );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry2.morphAttributes[ name ] = morphArray;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry2.morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tvar groups = this.groups;\r\n\r\n\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\tgeometry2.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometry2;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'BufferGeometry',\r\n\t\t\t\t\tgenerator: 'BufferGeometry.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard BufferGeometry serialization\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\t\t\tif ( Object.keys( this.userData ).length > 0 ) { data.userData = this.userData; }\r\n\r\n\t\t\tif ( this.parameters !== undefined ) {\r\n\r\n\t\t\t\tvar parameters = this.parameters;\r\n\r\n\t\t\t\tfor ( var key in parameters ) {\r\n\r\n\t\t\t\t\tif ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn data;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdata.data = { attributes: {} };\r\n\r\n\t\t\tvar index = this.index;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tdata.data.index = {\r\n\t\t\t\t\ttype: index.array.constructor.name,\r\n\t\t\t\t\tarray: Array.prototype.slice.call( index.array )\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = this.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ key ];\r\n\r\n\t\t\t\tvar attributeData = attribute.toJSON();\r\n\r\n\t\t\t\tif ( attribute.name !== '' ) { attributeData.name = attribute.name; }\r\n\r\n\t\t\t\tdata.data.attributes[ key ] = attributeData;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphAttributes = {};\r\n\t\t\tvar hasMorphAttributes = false;\r\n\r\n\t\t\tfor ( var key in this.morphAttributes ) {\r\n\r\n\t\t\t\tvar attributeArray = this.morphAttributes[ key ];\r\n\r\n\t\t\t\tvar array = [];\r\n\r\n\t\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar attribute = attributeArray[ i ];\r\n\r\n\t\t\t\t\tvar attributeData = attribute.toJSON();\r\n\r\n\t\t\t\t\tif ( attribute.name !== '' ) { attributeData.name = attribute.name; }\r\n\r\n\t\t\t\t\tarray.push( attributeData );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( array.length > 0 ) {\r\n\r\n\t\t\t\t\tmorphAttributes[ key ] = array;\r\n\r\n\t\t\t\t\thasMorphAttributes = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( hasMorphAttributes ) {\r\n\r\n\t\t\t\tdata.data.morphAttributes = morphAttributes;\r\n\t\t\t\tdata.data.morphTargetsRelative = this.morphTargetsRelative;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = this.groups;\r\n\r\n\t\t\tif ( groups.length > 0 ) {\r\n\r\n\t\t\t\tdata.data.groups = JSON.parse( JSON.stringify( groups ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundingSphere = this.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tdata.data.boundingSphere = {\r\n\t\t\t\t\tcenter: boundingSphere.center.toArray(),\r\n\t\t\t\t\tradius: boundingSphere.radius\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\t/*\r\n\t\t\t // Handle primitives\r\n\r\n\t\t\t var parameters = this.parameters;\r\n\r\n\t\t\t if ( parameters !== undefined ) {\r\n\r\n\t\t\t var values = [];\r\n\r\n\t\t\t for ( var key in parameters ) {\r\n\r\n\t\t\t values.push( parameters[ key ] );\r\n\r\n\t\t\t }\r\n\r\n\t\t\t var geometry = Object.create( this.constructor.prototype );\r\n\t\t\t this.constructor.apply( geometry, values );\r\n\t\t\t return geometry;\r\n\r\n\t\t\t }\r\n\r\n\t\t\t return new this.constructor().copy( this );\r\n\t\t\t */\r\n\r\n\t\t\treturn new BufferGeometry().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tvar name, i, l;\r\n\r\n\t\t\t// reset\r\n\r\n\t\t\tthis.index = null;\r\n\t\t\tthis.attributes = {};\r\n\t\t\tthis.morphAttributes = {};\r\n\t\t\tthis.groups = [];\r\n\t\t\tthis.boundingBox = null;\r\n\t\t\tthis.boundingSphere = null;\r\n\r\n\t\t\t// name\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\t// index\r\n\r\n\t\t\tvar index = source.index;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tthis.setIndex( index.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// attributes\r\n\r\n\t\t\tvar attributes = source.attributes;\r\n\r\n\t\t\tfor ( name in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ name ];\r\n\t\t\t\tthis.setAttribute( name, attribute.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph attributes\r\n\r\n\t\t\tvar morphAttributes = source.morphAttributes;\r\n\r\n\t\t\tfor ( name in morphAttributes ) {\r\n\r\n\t\t\t\tvar array = [];\r\n\t\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\r\n\r\n\t\t\t\tfor ( i = 0, l = morphAttribute.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tarray.push( morphAttribute[ i ].clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphAttributes[ name ] = array;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.morphTargetsRelative = source.morphTargetsRelative;\r\n\r\n\t\t\t// groups\r\n\r\n\t\t\tvar groups = source.groups;\r\n\r\n\t\t\tfor ( i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\tthis.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding box\r\n\r\n\t\t\tvar boundingBox = source.boundingBox;\r\n\r\n\t\t\tif ( boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding sphere\r\n\r\n\t\t\tvar boundingSphere = source.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// draw range\r\n\r\n\t\t\tthis.drawRange.start = source.drawRange.start;\r\n\t\t\tthis.drawRange.count = source.drawRange.count;\r\n\r\n\t\t\t// user data\r\n\r\n\t\t\tthis.userData = source.userData;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author jonobr1 / http://jonobr1.com/\r\n\t */\r\n\r\n\tvar _inverseMatrix = new Matrix4();\r\n\tvar _ray = new Ray();\r\n\tvar _sphere = new Sphere();\r\n\r\n\tvar _vA = new Vector3();\r\n\tvar _vB = new Vector3();\r\n\tvar _vC = new Vector3();\r\n\r\n\tvar _tempA = new Vector3();\r\n\tvar _tempB = new Vector3();\r\n\tvar _tempC = new Vector3();\r\n\r\n\tvar _morphA = new Vector3();\r\n\tvar _morphB = new Vector3();\r\n\tvar _morphC = new Vector3();\r\n\r\n\tvar _uvA = new Vector2();\r\n\tvar _uvB = new Vector2();\r\n\tvar _uvC = new Vector2();\r\n\r\n\tvar _intersectionPoint = new Vector3();\r\n\tvar _intersectionPointWorld = new Vector3();\r\n\r\n\tfunction Mesh( geometry, material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Mesh';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t\tthis.updateMorphTargets();\r\n\r\n\t}\r\n\r\n\tMesh.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Mesh,\r\n\r\n\t\tisMesh: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tif ( source.morphTargetInfluences !== undefined ) {\r\n\r\n\t\t\t\tthis.morphTargetInfluences = source.morphTargetInfluences.slice();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( source.morphTargetDictionary !== undefined ) {\r\n\r\n\t\t\t\tthis.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar m, ml, name;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\t\t\t\tvar keys = Object.keys( morphAttributes );\r\n\r\n\t\t\t\tif ( keys.length > 0 ) {\r\n\r\n\t\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\r\n\r\n\t\t\t\t\tif ( morphAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.morphTargetInfluences = [];\r\n\t\t\t\t\t\tthis.morphTargetDictionary = {};\r\n\r\n\t\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\r\n\r\n\t\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\r\n\r\n\t\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\r\n\t\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar morphTargets = geometry.morphTargets;\r\n\r\n\t\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar material = this.material;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\r\n\t\t\tif ( material === undefined ) { return; }\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere.copy( geometry.boundingSphere );\r\n\t\t\t_sphere.applyMatrix4( matrixWorld );\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix.getInverse( matrixWorld );\r\n\t\t\t_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );\r\n\r\n\t\t\t// Check boundingBox before continuing\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tif ( _ray.intersectsBox( geometry.boundingBox ) === false ) { return; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar intersection;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar a, b, c;\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar position = geometry.attributes.position;\r\n\t\t\t\tvar morphPosition = geometry.morphAttributes.position;\r\n\t\t\t\tvar morphTargetsRelative = geometry.morphTargetsRelative;\r\n\t\t\t\tvar uv = geometry.attributes.uv;\r\n\t\t\t\tvar uv2 = geometry.attributes.uv2;\r\n\t\t\t\tvar groups = geometry.groups;\r\n\t\t\t\tvar drawRange = geometry.drawRange;\r\n\t\t\t\tvar i, j, il, jl;\r\n\t\t\t\tvar group, groupMaterial;\r\n\t\t\t\tvar start, end;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\t// indexed buffer geometry\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tgroup = groups[ i ];\r\n\t\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\r\n\t\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\ta = index.getX( j );\r\n\t\t\t\t\t\t\t\tb = index.getX( j + 1 );\r\n\t\t\t\t\t\t\t\tc = index.getX( j + 2 );\r\n\r\n\t\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics\r\n\t\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\r\n\t\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstart = Math.max( 0, drawRange.start );\r\n\t\t\t\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\ta = index.getX( i );\r\n\t\t\t\t\t\t\tb = index.getX( i + 1 );\r\n\t\t\t\t\t\t\tc = index.getX( i + 2 );\r\n\r\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics\r\n\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( position !== undefined ) {\r\n\r\n\t\t\t\t\t// non-indexed buffer geometry\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tgroup = groups[ i ];\r\n\t\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\r\n\t\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\t\t\ta = j;\r\n\t\t\t\t\t\t\t\tb = j + 1;\r\n\t\t\t\t\t\t\t\tc = j + 2;\r\n\r\n\t\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics\r\n\t\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\r\n\t\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstart = Math.max( 0, drawRange.start );\r\n\t\t\t\t\t\tend = Math.min( position.count, ( drawRange.start + drawRange.count ) );\r\n\r\n\t\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\r\n\r\n\t\t\t\t\t\t\ta = i;\r\n\t\t\t\t\t\t\tb = i + 1;\r\n\t\t\t\t\t\t\tc = i + 2;\r\n\r\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\r\n\r\n\t\t\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics\r\n\t\t\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar fvA, fvB, fvC;\r\n\t\t\t\tvar isMultiMaterial = Array.isArray( material );\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar faces = geometry.faces;\r\n\t\t\t\tvar uvs;\r\n\r\n\t\t\t\tvar faceVertexUvs = geometry.faceVertexUvs[ 0 ];\r\n\t\t\t\tif ( faceVertexUvs.length > 0 ) { uvs = faceVertexUvs; }\r\n\r\n\t\t\t\tfor ( var f = 0, fl = faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tvar face = faces[ f ];\r\n\t\t\t\t\tvar faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;\r\n\r\n\t\t\t\t\tif ( faceMaterial === undefined ) { continue; }\r\n\r\n\t\t\t\t\tfvA = vertices[ face.a ];\r\n\t\t\t\t\tfvB = vertices[ face.b ];\r\n\t\t\t\t\tfvC = vertices[ face.c ];\r\n\r\n\t\t\t\t\tintersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );\r\n\r\n\t\t\t\t\tif ( intersection ) {\r\n\r\n\t\t\t\t\t\tif ( uvs && uvs[ f ] ) {\r\n\r\n\t\t\t\t\t\t\tvar uvs_f = uvs[ f ];\r\n\t\t\t\t\t\t\t_uvA.copy( uvs_f[ 0 ] );\r\n\t\t\t\t\t\t\t_uvB.copy( uvs_f[ 1 ] );\r\n\t\t\t\t\t\t\t_uvC.copy( uvs_f[ 2 ] );\r\n\r\n\t\t\t\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tintersection.face = face;\r\n\t\t\t\t\t\tintersection.faceIndex = f;\r\n\t\t\t\t\t\tintersects.push( intersection );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {\r\n\r\n\t\tvar intersect;\r\n\r\n\t\tif ( material.side === BackSide ) {\r\n\r\n\t\t\tintersect = ray.intersectTriangle( pC, pB, pA, true, point );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tintersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );\r\n\r\n\t\t}\r\n\r\n\t\tif ( intersect === null ) { return null; }\r\n\r\n\t\t_intersectionPointWorld.copy( point );\r\n\t\t_intersectionPointWorld.applyMatrix4( object.matrixWorld );\r\n\r\n\t\tvar distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );\r\n\r\n\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return null; }\r\n\r\n\t\treturn {\r\n\t\t\tdistance: distance,\r\n\t\t\tpoint: _intersectionPointWorld.clone(),\r\n\t\t\tobject: object\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {\r\n\r\n\t\t_vA.fromBufferAttribute( position, a );\r\n\t\t_vB.fromBufferAttribute( position, b );\r\n\t\t_vC.fromBufferAttribute( position, c );\r\n\r\n\t\tvar morphInfluences = object.morphTargetInfluences;\r\n\r\n\t\tif ( material.morphTargets && morphPosition && morphInfluences ) {\r\n\r\n\t\t\t_morphA.set( 0, 0, 0 );\r\n\t\t\t_morphB.set( 0, 0, 0 );\r\n\t\t\t_morphC.set( 0, 0, 0 );\r\n\r\n\t\t\tfor ( var i = 0, il = morphPosition.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar influence = morphInfluences[ i ];\r\n\t\t\t\tvar morphAttribute = morphPosition[ i ];\r\n\r\n\t\t\t\tif ( influence === 0 ) { continue; }\r\n\r\n\t\t\t\t_tempA.fromBufferAttribute( morphAttribute, a );\r\n\t\t\t\t_tempB.fromBufferAttribute( morphAttribute, b );\r\n\t\t\t\t_tempC.fromBufferAttribute( morphAttribute, c );\r\n\r\n\t\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\t\t_morphA.addScaledVector( _tempA, influence );\r\n\t\t\t\t\t_morphB.addScaledVector( _tempB, influence );\r\n\t\t\t\t\t_morphC.addScaledVector( _tempC, influence );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\r\n\t\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\r\n\t\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_vA.add( _morphA );\r\n\t\t\t_vB.add( _morphB );\r\n\t\t\t_vC.add( _morphC );\r\n\r\n\t\t}\r\n\r\n\t\tvar intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );\r\n\r\n\t\tif ( intersection ) {\r\n\r\n\t\t\tif ( uv ) {\r\n\r\n\t\t\t\t_uvA.fromBufferAttribute( uv, a );\r\n\t\t\t\t_uvB.fromBufferAttribute( uv, b );\r\n\t\t\t\t_uvC.fromBufferAttribute( uv, c );\r\n\r\n\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv2 ) {\r\n\r\n\t\t\t\t_uvA.fromBufferAttribute( uv2, a );\r\n\t\t\t\t_uvB.fromBufferAttribute( uv2, b );\r\n\t\t\t\t_uvC.fromBufferAttribute( uv2, c );\r\n\r\n\t\t\t\tintersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar face = new Face3( a, b, c );\r\n\t\t\tTriangle.getNormal( _vA, _vB, _vC, face.normal );\r\n\r\n\t\t\tintersection.face = face;\r\n\r\n\t\t}\r\n\r\n\t\treturn intersection;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author kile / http://kile.stravaganza.org/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _geometryId = 0; // Geometry uses even numbers as Id\r\n\tvar _m1$3 = new Matrix4();\r\n\tvar _obj$1 = new Object3D();\r\n\tvar _offset$1 = new Vector3();\r\n\r\n\tfunction Geometry() {\r\n\r\n\t\tObject.defineProperty( this, 'id', { value: _geometryId += 2 } );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.name = '';\r\n\t\tthis.type = 'Geometry';\r\n\r\n\t\tthis.vertices = [];\r\n\t\tthis.colors = [];\r\n\t\tthis.faces = [];\r\n\t\tthis.faceVertexUvs = [[]];\r\n\r\n\t\tthis.morphTargets = [];\r\n\t\tthis.morphNormals = [];\r\n\r\n\t\tthis.skinWeights = [];\r\n\t\tthis.skinIndices = [];\r\n\r\n\t\tthis.lineDistances = [];\r\n\r\n\t\tthis.boundingBox = null;\r\n\t\tthis.boundingSphere = null;\r\n\r\n\t\t// update flags\r\n\r\n\t\tthis.elementsNeedUpdate = false;\r\n\t\tthis.verticesNeedUpdate = false;\r\n\t\tthis.uvsNeedUpdate = false;\r\n\t\tthis.normalsNeedUpdate = false;\r\n\t\tthis.colorsNeedUpdate = false;\r\n\t\tthis.lineDistancesNeedUpdate = false;\r\n\t\tthis.groupsNeedUpdate = false;\r\n\r\n\t}\r\n\r\n\tGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: Geometry,\r\n\r\n\t\tisGeometry: true,\r\n\r\n\t\tapplyMatrix: function ( matrix ) {\r\n\r\n\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\tfor ( var i = 0, il = this.vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = this.vertices[ i ];\r\n\t\t\t\tvertex.applyMatrix4( matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, il = this.faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ i ];\r\n\t\t\t\tface.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tface.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.verticesNeedUpdate = true;\r\n\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateX: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world x-axis\r\n\r\n\t\t\t_m1$3.makeRotationX( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateY: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world y-axis\r\n\r\n\t\t\t_m1$3.makeRotationY( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\trotateZ: function ( angle ) {\r\n\r\n\t\t\t// rotate geometry around world z-axis\r\n\r\n\t\t\t_m1$3.makeRotationZ( angle );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( x, y, z ) {\r\n\r\n\t\t\t// translate geometry\r\n\r\n\t\t\t_m1$3.makeTranslation( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tscale: function ( x, y, z ) {\r\n\r\n\t\t\t// scale geometry\r\n\r\n\t\t\t_m1$3.makeScale( x, y, z );\r\n\r\n\t\t\tthis.applyMatrix( _m1$3 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlookAt: function ( vector ) {\r\n\r\n\t\t\t_obj$1.lookAt( vector );\r\n\r\n\t\t\t_obj$1.updateMatrix();\r\n\r\n\t\t\tthis.applyMatrix( _obj$1.matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tfromBufferGeometry: function ( geometry ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar indices = geometry.index !== null ? geometry.index.array : undefined;\r\n\t\t\tvar attributes = geometry.attributes;\r\n\r\n\t\t\tif ( attributes.position === undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar positions = attributes.position.array;\r\n\t\t\tvar normals = attributes.normal !== undefined ? attributes.normal.array : undefined;\r\n\t\t\tvar colors = attributes.color !== undefined ? attributes.color.array : undefined;\r\n\t\t\tvar uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;\r\n\t\t\tvar uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;\r\n\r\n\t\t\tif ( uvs2 !== undefined ) { this.faceVertexUvs[ 1 ] = []; }\r\n\r\n\t\t\tfor ( var i = 0; i < positions.length; i += 3 ) {\r\n\r\n\t\t\t\tscope.vertices.push( new Vector3().fromArray( positions, i ) );\r\n\r\n\t\t\t\tif ( colors !== undefined ) {\r\n\r\n\t\t\t\t\tscope.colors.push( new Color().fromArray( colors, i ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction addFace( a, b, c, materialIndex ) {\r\n\r\n\t\t\t\tvar vertexColors = ( colors === undefined ) ? [] : [\r\n\t\t\t\t\tscope.colors[ a ].clone(),\r\n\t\t\t\t\tscope.colors[ b ].clone(),\r\n\t\t\t\t\tscope.colors[ c ].clone() ];\r\n\r\n\t\t\t\tvar vertexNormals = ( normals === undefined ) ? [] : [\r\n\t\t\t\t\tnew Vector3().fromArray( normals, a * 3 ),\r\n\t\t\t\t\tnew Vector3().fromArray( normals, b * 3 ),\r\n\t\t\t\t\tnew Vector3().fromArray( normals, c * 3 )\r\n\t\t\t\t];\r\n\r\n\t\t\t\tvar face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );\r\n\r\n\t\t\t\tscope.faces.push( face );\r\n\r\n\t\t\t\tif ( uvs !== undefined ) {\r\n\r\n\t\t\t\t\tscope.faceVertexUvs[ 0 ].push( [\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, a * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, b * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs, c * 2 )\r\n\t\t\t\t\t] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uvs2 !== undefined ) {\r\n\r\n\t\t\t\t\tscope.faceVertexUvs[ 1 ].push( [\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, a * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, b * 2 ),\r\n\t\t\t\t\t\tnew Vector2().fromArray( uvs2, c * 2 )\r\n\t\t\t\t\t] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\tif ( groups.length > 0 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < groups.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar group = groups[ i ];\r\n\r\n\t\t\t\t\tvar start = group.start;\r\n\t\t\t\t\tvar count = group.count;\r\n\r\n\t\t\t\t\tfor ( var j = start, jl = start + count; j < jl; j += 3 ) {\r\n\r\n\t\t\t\t\t\tif ( indices !== undefined ) {\r\n\r\n\t\t\t\t\t\t\taddFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\taddFace( j, j + 1, j + 2, group.materialIndex );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( indices !== undefined ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\r\n\r\n\t\t\t\t\t\taddFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < positions.length / 3; i += 3 ) {\r\n\r\n\t\t\t\t\t\taddFace( i, i + 1, i + 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\tif ( geometry.boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( geometry.boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function () {\r\n\r\n\t\t\tthis.computeBoundingBox();\r\n\r\n\t\t\tthis.boundingBox.getCenter( _offset$1 ).negate();\r\n\r\n\t\t\tthis.translate( _offset$1.x, _offset$1.y, _offset$1.z );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tnormalize: function () {\r\n\r\n\t\t\tthis.computeBoundingSphere();\r\n\r\n\t\t\tvar center = this.boundingSphere.center;\r\n\t\t\tvar radius = this.boundingSphere.radius;\r\n\r\n\t\t\tvar s = radius === 0 ? 1 : 1.0 / radius;\r\n\r\n\t\t\tvar matrix = new Matrix4();\r\n\t\t\tmatrix.set(\r\n\t\t\t\ts, 0, 0, - s * center.x,\r\n\t\t\t\t0, s, 0, - s * center.y,\r\n\t\t\t\t0, 0, s, - s * center.z,\r\n\t\t\t\t0, 0, 0, 1\r\n\t\t\t);\r\n\r\n\t\t\tthis.applyMatrix( matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFaceNormals: function () {\r\n\r\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\tfor ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ f ];\r\n\r\n\t\t\t\tvar vA = this.vertices[ face.a ];\r\n\t\t\t\tvar vB = this.vertices[ face.b ];\r\n\t\t\t\tvar vC = this.vertices[ face.c ];\r\n\r\n\t\t\t\tcb.subVectors( vC, vB );\r\n\t\t\t\tab.subVectors( vA, vB );\r\n\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\tcb.normalize();\r\n\r\n\t\t\t\tface.normal.copy( cb );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeVertexNormals: function ( areaWeighted ) {\r\n\r\n\t\t\tif ( areaWeighted === undefined ) { areaWeighted = true; }\r\n\r\n\t\t\tvar v, vl, f, fl, face, vertices;\r\n\r\n\t\t\tvertices = new Array( this.vertices.length );\r\n\r\n\t\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\r\n\r\n\t\t\t\tvertices[ v ] = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( areaWeighted ) {\r\n\r\n\t\t\t\t// vertex normals weighted by triangle areas\r\n\t\t\t\t// http://www.iquilezles.org/www/articles/normals/normals.htm\r\n\r\n\t\t\t\tvar vA, vB, vC;\r\n\t\t\t\tvar cb = new Vector3(), ab = new Vector3();\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tvA = this.vertices[ face.a ];\r\n\t\t\t\t\tvB = this.vertices[ face.b ];\r\n\t\t\t\t\tvC = this.vertices[ face.c ];\r\n\r\n\t\t\t\t\tcb.subVectors( vC, vB );\r\n\t\t\t\t\tab.subVectors( vA, vB );\r\n\t\t\t\t\tcb.cross( ab );\r\n\r\n\t\t\t\t\tvertices[ face.a ].add( cb );\r\n\t\t\t\t\tvertices[ face.b ].add( cb );\r\n\t\t\t\t\tvertices[ face.c ].add( cb );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tvertices[ face.a ].add( face.normal );\r\n\t\t\t\t\tvertices[ face.b ].add( face.normal );\r\n\t\t\t\t\tvertices[ face.c ].add( face.normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\r\n\r\n\t\t\t\tvertices[ v ].normalize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ].copy( vertices[ face.a ] );\r\n\t\t\t\t\tvertexNormals[ 1 ].copy( vertices[ face.b ] );\r\n\t\t\t\t\tvertexNormals[ 2 ].copy( vertices[ face.c ] );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ] = vertices[ face.a ].clone();\r\n\t\t\t\t\tvertexNormals[ 1 ] = vertices[ face.b ].clone();\r\n\t\t\t\t\tvertexNormals[ 2 ] = vertices[ face.c ].clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.faces.length > 0 ) {\r\n\r\n\t\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFlatVertexNormals: function () {\r\n\r\n\t\t\tvar f, fl, face;\r\n\r\n\t\t\tthis.computeFaceNormals();\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\tif ( vertexNormals.length === 3 ) {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ].copy( face.normal );\r\n\t\t\t\t\tvertexNormals[ 1 ].copy( face.normal );\r\n\t\t\t\t\tvertexNormals[ 2 ].copy( face.normal );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvertexNormals[ 0 ] = face.normal.clone();\r\n\t\t\t\t\tvertexNormals[ 1 ] = face.normal.clone();\r\n\t\t\t\t\tvertexNormals[ 2 ] = face.normal.clone();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.faces.length > 0 ) {\r\n\r\n\t\t\t\tthis.normalsNeedUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeMorphNormals: function () {\r\n\r\n\t\t\tvar i, il, f, fl, face;\r\n\r\n\t\t\t// save original normals\r\n\t\t\t// - create temp variables on first access\r\n\t\t\t// otherwise just copy (for faster repeated calls)\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tif ( ! face.__originalFaceNormal ) {\r\n\r\n\t\t\t\t\tface.__originalFaceNormal = face.normal.clone();\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tface.__originalFaceNormal.copy( face.normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( ! face.__originalVertexNormals ) { face.__originalVertexNormals = []; }\r\n\r\n\t\t\t\tfor ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tif ( ! face.__originalVertexNormals[ i ] ) {\r\n\r\n\t\t\t\t\t\tface.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tface.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// use temp geometry to compute face and vertex normals for each morph\r\n\r\n\t\t\tvar tmpGeo = new Geometry();\r\n\t\t\ttmpGeo.faces = this.faces;\r\n\r\n\t\t\tfor ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// create on first access\r\n\r\n\t\t\t\tif ( ! this.morphNormals[ i ] ) {\r\n\r\n\t\t\t\t\tthis.morphNormals[ i ] = {};\r\n\t\t\t\t\tthis.morphNormals[ i ].faceNormals = [];\r\n\t\t\t\t\tthis.morphNormals[ i ].vertexNormals = [];\r\n\r\n\t\t\t\t\tvar dstNormalsFace = this.morphNormals[ i ].faceNormals;\r\n\t\t\t\t\tvar dstNormalsVertex = this.morphNormals[ i ].vertexNormals;\r\n\r\n\t\t\t\t\tvar faceNormal, vertexNormals;\r\n\r\n\t\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\t\tfaceNormal = new Vector3();\r\n\t\t\t\t\t\tvertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };\r\n\r\n\t\t\t\t\t\tdstNormalsFace.push( faceNormal );\r\n\t\t\t\t\t\tdstNormalsVertex.push( vertexNormals );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar morphNormals = this.morphNormals[ i ];\r\n\r\n\t\t\t\t// set vertices to morph target\r\n\r\n\t\t\t\ttmpGeo.vertices = this.morphTargets[ i ].vertices;\r\n\r\n\t\t\t\t// compute morph normals\r\n\r\n\t\t\t\ttmpGeo.computeFaceNormals();\r\n\t\t\t\ttmpGeo.computeVertexNormals();\r\n\r\n\t\t\t\t// store morph normals\r\n\r\n\t\t\t\tvar faceNormal, vertexNormals;\r\n\r\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\t\tfaceNormal = morphNormals.faceNormals[ f ];\r\n\t\t\t\t\tvertexNormals = morphNormals.vertexNormals[ f ];\r\n\r\n\t\t\t\t\tfaceNormal.copy( face.normal );\r\n\r\n\t\t\t\t\tvertexNormals.a.copy( face.vertexNormals[ 0 ] );\r\n\t\t\t\t\tvertexNormals.b.copy( face.vertexNormals[ 1 ] );\r\n\t\t\t\t\tvertexNormals.c.copy( face.vertexNormals[ 2 ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// restore original normals\r\n\r\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ f ];\r\n\r\n\t\t\t\tface.normal = face.__originalFaceNormal;\r\n\t\t\t\tface.vertexNormals = face.__originalVertexNormals;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingBox: function () {\r\n\r\n\t\t\tif ( this.boundingBox === null ) {\r\n\r\n\t\t\t\tthis.boundingBox = new Box3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.boundingBox.setFromPoints( this.vertices );\r\n\r\n\t\t},\r\n\r\n\t\tcomputeBoundingSphere: function () {\r\n\r\n\t\t\tif ( this.boundingSphere === null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = new Sphere();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.boundingSphere.setFromPoints( this.vertices );\r\n\r\n\t\t},\r\n\r\n\t\tmerge: function ( geometry, matrix, materialIndexOffset ) {\r\n\r\n\t\t\tif ( ! ( geometry && geometry.isGeometry ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar normalMatrix,\r\n\t\t\t\tvertexOffset = this.vertices.length,\r\n\t\t\t\tvertices1 = this.vertices,\r\n\t\t\t\tvertices2 = geometry.vertices,\r\n\t\t\t\tfaces1 = this.faces,\r\n\t\t\t\tfaces2 = geometry.faces,\r\n\t\t\t\tcolors1 = this.colors,\r\n\t\t\t\tcolors2 = geometry.colors;\r\n\r\n\t\t\tif ( materialIndexOffset === undefined ) { materialIndexOffset = 0; }\r\n\r\n\t\t\tif ( matrix !== undefined ) {\r\n\r\n\t\t\t\tnormalMatrix = new Matrix3().getNormalMatrix( matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// vertices\r\n\r\n\t\t\tfor ( var i = 0, il = vertices2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = vertices2[ i ];\r\n\r\n\t\t\t\tvar vertexCopy = vertex.clone();\r\n\r\n\t\t\t\tif ( matrix !== undefined ) { vertexCopy.applyMatrix4( matrix ); }\r\n\r\n\t\t\t\tvertices1.push( vertexCopy );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// colors\r\n\r\n\t\t\tfor ( var i = 0, il = colors2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tcolors1.push( colors2[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// faces\r\n\r\n\t\t\tfor ( i = 0, il = faces2.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces2[ i ], faceCopy, normal, color,\r\n\t\t\t\t\tfaceVertexNormals = face.vertexNormals,\r\n\t\t\t\t\tfaceVertexColors = face.vertexColors;\r\n\r\n\t\t\t\tfaceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );\r\n\t\t\t\tfaceCopy.normal.copy( face.normal );\r\n\r\n\t\t\t\tif ( normalMatrix !== undefined ) {\r\n\r\n\t\t\t\t\tfaceCopy.normal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tnormal = faceVertexNormals[ j ].clone();\r\n\r\n\t\t\t\t\tif ( normalMatrix !== undefined ) {\r\n\r\n\t\t\t\t\t\tnormal.applyMatrix3( normalMatrix ).normalize();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfaceCopy.vertexNormals.push( normal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfaceCopy.color.copy( face.color );\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tcolor = faceVertexColors[ j ];\r\n\t\t\t\t\tfaceCopy.vertexColors.push( color.clone() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfaceCopy.materialIndex = face.materialIndex + materialIndexOffset;\r\n\r\n\t\t\t\tfaces1.push( faceCopy );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uvs\r\n\r\n\t\t\tfor ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar faceVertexUvs2 = geometry.faceVertexUvs[ i ];\r\n\r\n\t\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) { this.faceVertexUvs[ i ] = []; }\r\n\r\n\t\t\t\tfor ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar uvs2 = faceVertexUvs2[ j ], uvsCopy = [];\r\n\r\n\t\t\t\t\tfor ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\tuvsCopy.push( uvs2[ k ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tmergeMesh: function ( mesh ) {\r\n\r\n\t\t\tif ( ! ( mesh && mesh.isMesh ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( mesh.matrixAutoUpdate ) { mesh.updateMatrix(); }\r\n\r\n\t\t\tthis.merge( mesh.geometry, mesh.matrix );\r\n\r\n\t\t},\r\n\r\n\t\t/*\r\n\t\t * Checks for duplicate vertices with hashmap.\r\n\t\t * Duplicated vertices are removed\r\n\t\t * and faces' vertices are updated.\r\n\t\t */\r\n\r\n\t\tmergeVertices: function () {\r\n\r\n\t\t\tvar verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)\r\n\t\t\tvar unique = [], changes = [];\r\n\r\n\t\t\tvar v, key;\r\n\t\t\tvar precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001\r\n\t\t\tvar precision = Math.pow( 10, precisionPoints );\r\n\t\t\tvar i, il, face;\r\n\t\t\tvar indices, j, jl;\r\n\r\n\t\t\tfor ( i = 0, il = this.vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tv = this.vertices[ i ];\r\n\t\t\t\tkey = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );\r\n\r\n\t\t\t\tif ( verticesMap[ key ] === undefined ) {\r\n\r\n\t\t\t\t\tverticesMap[ key ] = i;\r\n\t\t\t\t\tunique.push( this.vertices[ i ] );\r\n\t\t\t\t\tchanges[ i ] = unique.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);\r\n\t\t\t\t\tchanges[ i ] = changes[ verticesMap[ key ] ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// if faces are completely degenerate after merging vertices, we\r\n\t\t\t// have to remove them from the geometry.\r\n\t\t\tvar faceIndicesToRemove = [];\r\n\r\n\t\t\tfor ( i = 0, il = this.faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tface = this.faces[ i ];\r\n\r\n\t\t\t\tface.a = changes[ face.a ];\r\n\t\t\t\tface.b = changes[ face.b ];\r\n\t\t\t\tface.c = changes[ face.c ];\r\n\r\n\t\t\t\tindices = [ face.a, face.b, face.c ];\r\n\r\n\t\t\t\t// if any duplicate vertices are found in a Face3\r\n\t\t\t\t// we have to remove the face as nothing can be saved\r\n\t\t\t\tfor ( var n = 0; n < 3; n ++ ) {\r\n\r\n\t\t\t\t\tif ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {\r\n\r\n\t\t\t\t\t\tfaceIndicesToRemove.push( i );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {\r\n\r\n\t\t\t\tvar idx = faceIndicesToRemove[ i ];\r\n\r\n\t\t\t\tthis.faces.splice( idx, 1 );\r\n\r\n\t\t\t\tfor ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ j ].splice( idx, 1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Use unique set of vertices\r\n\r\n\t\t\tvar diff = this.vertices.length - unique.length;\r\n\t\t\tthis.vertices = unique;\r\n\t\t\treturn diff;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.vertices = [];\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tthis.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsortFacesByMaterialIndex: function () {\r\n\r\n\t\t\tvar faces = this.faces;\r\n\t\t\tvar length = faces.length;\r\n\r\n\t\t\t// tag faces\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tfaces[ i ]._id = i;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// sort faces\r\n\r\n\t\t\tfunction materialIndexSort( a, b ) {\r\n\r\n\t\t\t\treturn a.materialIndex - b.materialIndex;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfaces.sort( materialIndexSort );\r\n\r\n\t\t\t// sort uvs\r\n\r\n\t\t\tvar uvs1 = this.faceVertexUvs[ 0 ];\r\n\t\t\tvar uvs2 = this.faceVertexUvs[ 1 ];\r\n\r\n\t\t\tvar newUvs1, newUvs2;\r\n\r\n\t\t\tif ( uvs1 && uvs1.length === length ) { newUvs1 = []; }\r\n\t\t\tif ( uvs2 && uvs2.length === length ) { newUvs2 = []; }\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar id = faces[ i ]._id;\r\n\r\n\t\t\t\tif ( newUvs1 ) { newUvs1.push( uvs1[ id ] ); }\r\n\t\t\t\tif ( newUvs2 ) { newUvs2.push( uvs2[ id ] ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( newUvs1 ) { this.faceVertexUvs[ 0 ] = newUvs1; }\r\n\t\t\tif ( newUvs2 ) { this.faceVertexUvs[ 1 ] = newUvs2; }\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Geometry',\r\n\t\t\t\t\tgenerator: 'Geometry.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\t// standard Geometry serialization\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.type = this.type;\r\n\t\t\tif ( this.name !== '' ) { data.name = this.name; }\r\n\r\n\t\t\tif ( this.parameters !== undefined ) {\r\n\r\n\t\t\t\tvar parameters = this.parameters;\r\n\r\n\t\t\t\tfor ( var key in parameters ) {\r\n\r\n\t\t\t\t\tif ( parameters[ key ] !== undefined ) { data[ key ] = parameters[ key ]; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn data;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar vertices = [];\r\n\r\n\t\t\tfor ( var i = 0; i < this.vertices.length; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = this.vertices[ i ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar faces = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar normalsHash = {};\r\n\t\t\tvar colors = [];\r\n\t\t\tvar colorsHash = {};\r\n\t\t\tvar uvs = [];\r\n\t\t\tvar uvsHash = {};\r\n\r\n\t\t\tfor ( var i = 0; i < this.faces.length; i ++ ) {\r\n\r\n\t\t\t\tvar face = this.faces[ i ];\r\n\r\n\t\t\t\tvar hasMaterial = true;\r\n\t\t\t\tvar hasFaceUv = false; // deprecated\r\n\t\t\t\tvar hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;\r\n\t\t\t\tvar hasFaceNormal = face.normal.length() > 0;\r\n\t\t\t\tvar hasFaceVertexNormal = face.vertexNormals.length > 0;\r\n\t\t\t\tvar hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;\r\n\t\t\t\tvar hasFaceVertexColor = face.vertexColors.length > 0;\r\n\r\n\t\t\t\tvar faceType = 0;\r\n\r\n\t\t\t\tfaceType = setBit( faceType, 0, 0 ); // isQuad\r\n\t\t\t\tfaceType = setBit( faceType, 1, hasMaterial );\r\n\t\t\t\tfaceType = setBit( faceType, 2, hasFaceUv );\r\n\t\t\t\tfaceType = setBit( faceType, 3, hasFaceVertexUv );\r\n\t\t\t\tfaceType = setBit( faceType, 4, hasFaceNormal );\r\n\t\t\t\tfaceType = setBit( faceType, 5, hasFaceVertexNormal );\r\n\t\t\t\tfaceType = setBit( faceType, 6, hasFaceColor );\r\n\t\t\t\tfaceType = setBit( faceType, 7, hasFaceVertexColor );\r\n\r\n\t\t\t\tfaces.push( faceType );\r\n\t\t\t\tfaces.push( face.a, face.b, face.c );\r\n\t\t\t\tfaces.push( face.materialIndex );\r\n\r\n\t\t\t\tif ( hasFaceVertexUv ) {\r\n\r\n\t\t\t\t\tvar faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 0 ] ),\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 1 ] ),\r\n\t\t\t\t\t\tgetUvIndex( faceVertexUvs[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceNormal ) {\r\n\r\n\t\t\t\t\tfaces.push( getNormalIndex( face.normal ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexNormal ) {\r\n\r\n\t\t\t\t\tvar vertexNormals = face.vertexNormals;\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 0 ] ),\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 1 ] ),\r\n\t\t\t\t\t\tgetNormalIndex( vertexNormals[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceColor ) {\r\n\r\n\t\t\t\t\tfaces.push( getColorIndex( face.color ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( hasFaceVertexColor ) {\r\n\r\n\t\t\t\t\tvar vertexColors = face.vertexColors;\r\n\r\n\t\t\t\t\tfaces.push(\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 0 ] ),\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 1 ] ),\r\n\t\t\t\t\t\tgetColorIndex( vertexColors[ 2 ] )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction setBit( value, position, enabled ) {\r\n\r\n\t\t\t\treturn enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getNormalIndex( normal ) {\r\n\r\n\t\t\t\tvar hash = normal.x.toString() + normal.y.toString() + normal.z.toString();\r\n\r\n\t\t\t\tif ( normalsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn normalsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnormalsHash[ hash ] = normals.length / 3;\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\treturn normalsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getColorIndex( color ) {\r\n\r\n\t\t\t\tvar hash = color.r.toString() + color.g.toString() + color.b.toString();\r\n\r\n\t\t\t\tif ( colorsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn colorsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcolorsHash[ hash ] = colors.length;\r\n\t\t\t\tcolors.push( color.getHex() );\r\n\r\n\t\t\t\treturn colorsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getUvIndex( uv ) {\r\n\r\n\t\t\t\tvar hash = uv.x.toString() + uv.y.toString();\r\n\r\n\t\t\t\tif ( uvsHash[ hash ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn uvsHash[ hash ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuvsHash[ hash ] = uvs.length / 2;\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\treturn uvsHash[ hash ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tdata.data = {};\r\n\r\n\t\t\tdata.data.vertices = vertices;\r\n\t\t\tdata.data.normals = normals;\r\n\t\t\tif ( colors.length > 0 ) { data.data.colors = colors; }\r\n\t\t\tif ( uvs.length > 0 ) { data.data.uvs = [ uvs ]; } // temporal backward compatibility\r\n\t\t\tdata.data.faces = faces;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\t/*\r\n\t\t\t // Handle primitives\r\n\r\n\t\t\t var parameters = this.parameters;\r\n\r\n\t\t\t if ( parameters !== undefined ) {\r\n\r\n\t\t\t var values = [];\r\n\r\n\t\t\t for ( var key in parameters ) {\r\n\r\n\t\t\t values.push( parameters[ key ] );\r\n\r\n\t\t\t }\r\n\r\n\t\t\t var geometry = Object.create( this.constructor.prototype );\r\n\t\t\t this.constructor.apply( geometry, values );\r\n\t\t\t return geometry;\r\n\r\n\t\t\t }\r\n\r\n\t\t\t return new this.constructor().copy( this );\r\n\t\t\t */\r\n\r\n\t\t\treturn new Geometry().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tvar i, il, j, jl, k, kl;\r\n\r\n\t\t\t// reset\r\n\r\n\t\t\tthis.vertices = [];\r\n\t\t\tthis.colors = [];\r\n\t\t\tthis.faces = [];\r\n\t\t\tthis.faceVertexUvs = [[]];\r\n\t\t\tthis.morphTargets = [];\r\n\t\t\tthis.morphNormals = [];\r\n\t\t\tthis.skinWeights = [];\r\n\t\t\tthis.skinIndices = [];\r\n\t\t\tthis.lineDistances = [];\r\n\t\t\tthis.boundingBox = null;\r\n\t\t\tthis.boundingSphere = null;\r\n\r\n\t\t\t// name\r\n\r\n\t\t\tthis.name = source.name;\r\n\r\n\t\t\t// vertices\r\n\r\n\t\t\tvar vertices = source.vertices;\r\n\r\n\t\t\tfor ( i = 0, il = vertices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.vertices.push( vertices[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// colors\r\n\r\n\t\t\tvar colors = source.colors;\r\n\r\n\t\t\tfor ( i = 0, il = colors.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.colors.push( colors[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// faces\r\n\r\n\t\t\tvar faces = source.faces;\r\n\r\n\t\t\tfor ( i = 0, il = faces.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.faces.push( faces[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// face vertex uvs\r\n\r\n\t\t\tfor ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar faceVertexUvs = source.faceVertexUvs[ i ];\r\n\r\n\t\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) {\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ] = [];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar uvs = faceVertexUvs[ j ], uvsCopy = [];\r\n\r\n\t\t\t\t\tfor ( k = 0, kl = uvs.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\tvar uv = uvs[ k ];\r\n\r\n\t\t\t\t\t\tuvsCopy.push( uv.clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph targets\r\n\r\n\t\t\tvar morphTargets = source.morphTargets;\r\n\r\n\t\t\tfor ( i = 0, il = morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphTarget = {};\r\n\t\t\t\tmorphTarget.name = morphTargets[ i ].name;\r\n\r\n\t\t\t\t// vertices\r\n\r\n\t\t\t\tif ( morphTargets[ i ].vertices !== undefined ) {\r\n\r\n\t\t\t\t\tmorphTarget.vertices = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// normals\r\n\r\n\t\t\t\tif ( morphTargets[ i ].normals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphTarget.normals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphTargets.push( morphTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph normals\r\n\r\n\t\t\tvar morphNormals = source.morphNormals;\r\n\r\n\t\t\tfor ( i = 0, il = morphNormals.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphNormal = {};\r\n\r\n\t\t\t\t// vertex normals\r\n\r\n\t\t\t\tif ( morphNormals[ i ].vertexNormals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphNormal.vertexNormals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tvar srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];\r\n\t\t\t\t\t\tvar destVertexNormal = {};\r\n\r\n\t\t\t\t\t\tdestVertexNormal.a = srcVertexNormal.a.clone();\r\n\t\t\t\t\t\tdestVertexNormal.b = srcVertexNormal.b.clone();\r\n\t\t\t\t\t\tdestVertexNormal.c = srcVertexNormal.c.clone();\r\n\r\n\t\t\t\t\t\tmorphNormal.vertexNormals.push( destVertexNormal );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// face normals\r\n\r\n\t\t\t\tif ( morphNormals[ i ].faceNormals !== undefined ) {\r\n\r\n\t\t\t\t\tmorphNormal.faceNormals = [];\r\n\r\n\t\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tmorphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.morphNormals.push( morphNormal );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skin weights\r\n\r\n\t\t\tvar skinWeights = source.skinWeights;\r\n\r\n\t\t\tfor ( i = 0, il = skinWeights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.skinWeights.push( skinWeights[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skin indices\r\n\r\n\t\t\tvar skinIndices = source.skinIndices;\r\n\r\n\t\t\tfor ( i = 0, il = skinIndices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.skinIndices.push( skinIndices[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// line distances\r\n\r\n\t\t\tvar lineDistances = source.lineDistances;\r\n\r\n\t\t\tfor ( i = 0, il = lineDistances.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.lineDistances.push( lineDistances[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding box\r\n\r\n\t\t\tvar boundingBox = source.boundingBox;\r\n\r\n\t\t\tif ( boundingBox !== null ) {\r\n\r\n\t\t\t\tthis.boundingBox = boundingBox.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// bounding sphere\r\n\r\n\t\t\tvar boundingSphere = source.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== null ) {\r\n\r\n\t\t\t\tthis.boundingSphere = boundingSphere.clone();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update flags\r\n\r\n\t\t\tthis.elementsNeedUpdate = source.elementsNeedUpdate;\r\n\t\t\tthis.verticesNeedUpdate = source.verticesNeedUpdate;\r\n\t\t\tthis.uvsNeedUpdate = source.uvsNeedUpdate;\r\n\t\t\tthis.normalsNeedUpdate = source.normalsNeedUpdate;\r\n\t\t\tthis.colorsNeedUpdate = source.colorsNeedUpdate;\r\n\t\t\tthis.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;\r\n\t\t\tthis.groupsNeedUpdate = source.groupsNeedUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdispose: function () {\r\n\r\n\t\t\tthis.dispatchEvent( { type: 'dispose' } );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// BoxGeometry\r\n\r\n\tvar BoxGeometry = /*@__PURE__*/(function (Geometry) {\n\t\tfunction BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {\r\n\r\n\t\t\tGeometry.call(this);\r\n\r\n\t\t\tthis.type = 'BoxGeometry';\r\n\r\n\t\t\tthis.parameters = {\r\n\t\t\t\twidth: width,\r\n\t\t\t\theight: height,\r\n\t\t\t\tdepth: depth,\r\n\t\t\t\twidthSegments: widthSegments,\r\n\t\t\t\theightSegments: heightSegments,\r\n\t\t\t\tdepthSegments: depthSegments\r\n\t\t\t};\r\n\r\n\t\t\tthis.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );\r\n\t\t\tthis.mergeVertices();\r\n\r\n\t\t}\n\n\t\tif ( Geometry ) BoxGeometry.__proto__ = Geometry;\n\t\tBoxGeometry.prototype = Object.create( Geometry && Geometry.prototype );\n\t\tBoxGeometry.prototype.constructor = BoxGeometry;\n\n\t\treturn BoxGeometry;\n\t}(Geometry));\r\n\r\n\t// BoxBufferGeometry\r\n\r\n\tvar BoxBufferGeometry = /*@__PURE__*/(function (BufferGeometry) {\n\t\tfunction BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) {\r\n\r\n\t\t\tBufferGeometry.call(this);\r\n\r\n\t\t\tthis.type = 'BoxBufferGeometry';\r\n\r\n\t\t\tthis.parameters = {\r\n\t\t\t\twidth: width,\r\n\t\t\t\theight: height,\r\n\t\t\t\tdepth: depth,\r\n\t\t\t\twidthSegments: widthSegments,\r\n\t\t\t\theightSegments: heightSegments,\r\n\t\t\t\tdepthSegments: depthSegments\r\n\t\t\t};\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\twidth = width || 1;\r\n\t\t\theight = height || 1;\r\n\t\t\tdepth = depth || 1;\r\n\r\n\t\t\t// segments\r\n\r\n\t\t\twidthSegments = Math.floor( widthSegments ) || 1;\r\n\t\t\theightSegments = Math.floor( heightSegments ) || 1;\r\n\t\t\tdepthSegments = Math.floor( depthSegments ) || 1;\r\n\r\n\t\t\t// buffers\r\n\r\n\t\t\tvar indices = [];\r\n\t\t\tvar vertices = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar uvs = [];\r\n\r\n\t\t\t// helper variables\r\n\r\n\t\t\tvar numberOfVertices = 0;\r\n\t\t\tvar groupStart = 0;\r\n\r\n\t\t\t// build each side of the box geometry\r\n\r\n\t\t\tbuildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px\r\n\t\t\tbuildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx\r\n\t\t\tbuildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py\r\n\t\t\tbuildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny\r\n\t\t\tbuildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz\r\n\t\t\tbuildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz\r\n\r\n\t\t\t// build geometry\r\n\r\n\t\t\tthis.setIndex( indices );\r\n\t\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t\tfunction buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {\r\n\r\n\t\t\t\tvar segmentWidth = width / gridX;\r\n\t\t\t\tvar segmentHeight = height / gridY;\r\n\r\n\t\t\t\tvar widthHalf = width / 2;\r\n\t\t\t\tvar heightHalf = height / 2;\r\n\t\t\t\tvar depthHalf = depth / 2;\r\n\r\n\t\t\t\tvar gridX1 = gridX + 1;\r\n\t\t\t\tvar gridY1 = gridY + 1;\r\n\r\n\t\t\t\tvar vertexCounter = 0;\r\n\t\t\t\tvar groupCount = 0;\r\n\r\n\t\t\t\tvar ix, iy;\r\n\r\n\t\t\t\tvar vector = new Vector3();\r\n\r\n\t\t\t\t// generate vertices, normals and uvs\r\n\r\n\t\t\t\tfor ( iy = 0; iy < gridY1; iy ++ ) {\r\n\r\n\t\t\t\t\tvar y = iy * segmentHeight - heightHalf;\r\n\r\n\t\t\t\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\r\n\r\n\t\t\t\t\t\tvar x = ix * segmentWidth - widthHalf;\r\n\r\n\t\t\t\t\t\t// set values to correct vector component\r\n\r\n\t\t\t\t\t\tvector[ u ] = x * udir;\r\n\t\t\t\t\t\tvector[ v ] = y * vdir;\r\n\t\t\t\t\t\tvector[ w ] = depthHalf;\r\n\r\n\t\t\t\t\t\t// now apply vector to vertex buffer\r\n\r\n\t\t\t\t\t\tvertices.push( vector.x, vector.y, vector.z );\r\n\r\n\t\t\t\t\t\t// set values to correct vector component\r\n\r\n\t\t\t\t\t\tvector[ u ] = 0;\r\n\t\t\t\t\t\tvector[ v ] = 0;\r\n\t\t\t\t\t\tvector[ w ] = depth > 0 ? 1 : - 1;\r\n\r\n\t\t\t\t\t\t// now apply vector to normal buffer\r\n\r\n\t\t\t\t\t\tnormals.push( vector.x, vector.y, vector.z );\r\n\r\n\t\t\t\t\t\t// uvs\r\n\r\n\t\t\t\t\t\tuvs.push( ix / gridX );\r\n\t\t\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\r\n\r\n\t\t\t\t\t\t// counters\r\n\r\n\t\t\t\t\t\tvertexCounter += 1;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\t// 1. you need three indices to draw a single face\r\n\t\t\t\t// 2. a single segment consists of two faces\r\n\t\t\t\t// 3. so we need to generate six (2*3) indices per segment\r\n\r\n\t\t\t\tfor ( iy = 0; iy < gridY; iy ++ ) {\r\n\r\n\t\t\t\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\r\n\r\n\t\t\t\t\t\tvar a = numberOfVertices + ix + gridX1 * iy;\r\n\t\t\t\t\t\tvar b = numberOfVertices + ix + gridX1 * ( iy + 1 );\r\n\t\t\t\t\t\tvar c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );\r\n\t\t\t\t\t\tvar d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;\r\n\r\n\t\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t\t\t// increase counter\r\n\r\n\t\t\t\t\t\tgroupCount += 6;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\t\tscope.addGroup( groupStart, groupCount, materialIndex );\r\n\r\n\t\t\t\t// calculate new start value for groups\r\n\r\n\t\t\t\tgroupStart += groupCount;\r\n\r\n\t\t\t\t// update total number of vertices\r\n\r\n\t\t\t\tnumberOfVertices += vertexCounter;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\n\n\t\tif ( BufferGeometry ) BoxBufferGeometry.__proto__ = BufferGeometry;\n\t\tBoxBufferGeometry.prototype = Object.create( BufferGeometry && BufferGeometry.prototype );\n\t\tBoxBufferGeometry.prototype.constructor = BoxBufferGeometry;\n\n\t\treturn BoxBufferGeometry;\n\t}(BufferGeometry));\n\n\t/**\r\n\t * Uniform Utilities\r\n\t */\r\n\r\n\tfunction cloneUniforms( src ) {\r\n\r\n\t\tvar dst = {};\r\n\r\n\t\tfor ( var u in src ) {\r\n\r\n\t\t\tdst[ u ] = {};\r\n\r\n\t\t\tfor ( var p in src[ u ] ) {\r\n\r\n\t\t\t\tvar property = src[ u ][ p ];\r\n\r\n\t\t\t\tif ( property && ( property.isColor ||\r\n\t\t\t\t\tproperty.isMatrix3 || property.isMatrix4 ||\r\n\t\t\t\t\tproperty.isVector2 || property.isVector3 || property.isVector4 ||\r\n\t\t\t\t\tproperty.isTexture ) ) {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property.clone();\r\n\r\n\t\t\t\t} else if ( Array.isArray( property ) ) {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property.slice();\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tdst[ u ][ p ] = property;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn dst;\r\n\r\n\t}\r\n\r\n\tfunction mergeUniforms( uniforms ) {\r\n\r\n\t\tvar merged = {};\r\n\r\n\t\tfor ( var u = 0; u < uniforms.length; u ++ ) {\r\n\r\n\t\t\tvar tmp = cloneUniforms( uniforms[ u ] );\r\n\r\n\t\t\tfor ( var p in tmp ) {\r\n\r\n\t\t\t\tmerged[ p ] = tmp[ p ];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn merged;\r\n\r\n\t}\r\n\r\n\t// Legacy\r\n\r\n\tvar UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };\n\n\tvar default_vertex = \"void main() {\\n\\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\\n}\";\n\n\tvar default_fragment = \"void main() {\\n\\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\\n}\";\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * defines: { \"label\" : \"value\" },\r\n\t * uniforms: { \"parameter1\": { value: 1.0 }, \"parameter2\": { value2: 2 } },\r\n\t *\r\n\t * fragmentShader: ,\r\n\t * vertexShader: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * lights: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction ShaderMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'ShaderMaterial';\r\n\r\n\t\tthis.defines = {};\r\n\t\tthis.uniforms = {};\r\n\r\n\t\tthis.vertexShader = default_vertex;\r\n\t\tthis.fragmentShader = default_fragment;\r\n\r\n\t\tthis.linewidth = 1;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false; // set to use scene fog\r\n\t\tthis.lights = false; // set to use scene lights\r\n\t\tthis.clipping = false; // set to use user-defined clipping planes\r\n\r\n\t\tthis.skinning = false; // set to use skinning attribute streams\r\n\t\tthis.morphTargets = false; // set to use morph targets\r\n\t\tthis.morphNormals = false; // set to use morph normals\r\n\r\n\t\tthis.extensions = {\r\n\t\t\tderivatives: false, // set to use derivatives\r\n\t\t\tfragDepth: false, // set to use fragment depth values\r\n\t\t\tdrawBuffers: false, // set to use draw buffers\r\n\t\t\tshaderTextureLOD: false // set to use shader texture LOD\r\n\t\t};\r\n\r\n\t\t// When rendered geometry doesn't include these attributes but the material does,\r\n\t\t// use these default values in WebGL. This avoids errors when buffer data is missing.\r\n\t\tthis.defaultAttributeValues = {\r\n\t\t\t'color': [ 1, 1, 1 ],\r\n\t\t\t'uv': [ 0, 0 ],\r\n\t\t\t'uv2': [ 0, 0 ]\r\n\t\t};\r\n\r\n\t\tthis.index0AttributeName = undefined;\r\n\t\tthis.uniformsNeedUpdate = false;\r\n\r\n\t\tif ( parameters !== undefined ) {\r\n\r\n\t\t\tif ( parameters.attributes !== undefined ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setValues( parameters );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tShaderMaterial.prototype = Object.create( Material.prototype );\r\n\tShaderMaterial.prototype.constructor = ShaderMaterial;\r\n\r\n\tShaderMaterial.prototype.isShaderMaterial = true;\r\n\r\n\tShaderMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.fragmentShader = source.fragmentShader;\r\n\t\tthis.vertexShader = source.vertexShader;\r\n\r\n\t\tthis.uniforms = cloneUniforms( source.uniforms );\r\n\r\n\t\tthis.defines = Object.assign( {}, source.defines );\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\tthis.lights = source.lights;\r\n\t\tthis.clipping = source.clipping;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\tthis.extensions = source.extensions;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tShaderMaterial.prototype.toJSON = function ( meta ) {\r\n\r\n\t\tvar data = Material.prototype.toJSON.call( this, meta );\r\n\r\n\t\tdata.uniforms = {};\r\n\r\n\t\tfor ( var name in this.uniforms ) {\r\n\r\n\t\t\tvar uniform = this.uniforms[ name ];\r\n\t\t\tvar value = uniform.value;\r\n\r\n\t\t\tif ( value && value.isTexture ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 't',\r\n\t\t\t\t\tvalue: value.toJSON( meta ).uuid\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isColor ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'c',\r\n\t\t\t\t\tvalue: value.getHex()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector2 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v2',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector3 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v3',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isVector4 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'v4',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isMatrix3 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'm3',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else if ( value && value.isMatrix4 ) {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\ttype: 'm4',\r\n\t\t\t\t\tvalue: value.toArray()\r\n\t\t\t\t};\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdata.uniforms[ name ] = {\r\n\t\t\t\t\tvalue: value\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( Object.keys( this.defines ).length > 0 ) { data.defines = this.defines; }\r\n\r\n\t\tdata.vertexShader = this.vertexShader;\r\n\t\tdata.fragmentShader = this.fragmentShader;\r\n\r\n\t\tvar extensions = {};\r\n\r\n\t\tfor ( var key in this.extensions ) {\r\n\r\n\t\t\tif ( this.extensions[ key ] === true ) { extensions[ key ] = true; }\r\n\r\n\t\t}\r\n\r\n\t\tif ( Object.keys( extensions ).length > 0 ) { data.extensions = extensions; }\r\n\r\n\t\treturn data;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t*/\r\n\r\n\tfunction Camera() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Camera';\r\n\r\n\t\tthis.matrixWorldInverse = new Matrix4();\r\n\r\n\t\tthis.projectionMatrix = new Matrix4();\r\n\t\tthis.projectionMatrixInverse = new Matrix4();\r\n\r\n\t}\r\n\r\n\tCamera.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Camera,\r\n\r\n\t\tisCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.matrixWorldInverse.copy( source.matrixWorldInverse );\r\n\r\n\t\t\tthis.projectionMatrix.copy( source.projectionMatrix );\r\n\t\t\tthis.projectionMatrixInverse.copy( source.projectionMatrixInverse );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetWorldDirection: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Camera: .getWorldDirection() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\tvar e = this.matrixWorld.elements;\r\n\r\n\t\t\treturn target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author greggman / http://games.greggman.com/\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction PerspectiveCamera( fov, aspect, near, far ) {\r\n\r\n\t\tCamera.call( this );\r\n\r\n\t\tthis.type = 'PerspectiveCamera';\r\n\r\n\t\tthis.fov = fov !== undefined ? fov : 50;\r\n\t\tthis.zoom = 1;\r\n\r\n\t\tthis.near = near !== undefined ? near : 0.1;\r\n\t\tthis.far = far !== undefined ? far : 2000;\r\n\t\tthis.focus = 10;\r\n\r\n\t\tthis.aspect = aspect !== undefined ? aspect : 1;\r\n\t\tthis.view = null;\r\n\r\n\t\tthis.filmGauge = 35;\t// width of the film (default in millimeters)\r\n\t\tthis.filmOffset = 0;\t// horizontal film offset (same unit as gauge)\r\n\r\n\t\tthis.updateProjectionMatrix();\r\n\r\n\t}\r\n\r\n\tPerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\r\n\r\n\t\tconstructor: PerspectiveCamera,\r\n\r\n\t\tisPerspectiveCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tCamera.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.fov = source.fov;\r\n\t\t\tthis.zoom = source.zoom;\r\n\r\n\t\t\tthis.near = source.near;\r\n\t\t\tthis.far = source.far;\r\n\t\t\tthis.focus = source.focus;\r\n\r\n\t\t\tthis.aspect = source.aspect;\r\n\t\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\r\n\r\n\t\t\tthis.filmGauge = source.filmGauge;\r\n\t\t\tthis.filmOffset = source.filmOffset;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Sets the FOV by focal length in respect to the current .filmGauge.\r\n\t\t *\r\n\t\t * The default film gauge is 35, so that the focal length can be specified for\r\n\t\t * a 35mm (full frame) camera.\r\n\t\t *\r\n\t\t * Values for focal length and film gauge must have the same unit.\r\n\t\t */\r\n\t\tsetFocalLength: function ( focalLength ) {\r\n\r\n\t\t\t// see http://www.bobatkins.com/photography/technical/field_of_view.html\r\n\t\t\tvar vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;\r\n\r\n\t\t\tthis.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope );\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Calculates the focal length from the current .fov and .filmGauge.\r\n\t\t */\r\n\t\tgetFocalLength: function () {\r\n\r\n\t\t\tvar vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov );\r\n\r\n\t\t\treturn 0.5 * this.getFilmHeight() / vExtentSlope;\r\n\r\n\t\t},\r\n\r\n\t\tgetEffectiveFOV: function () {\r\n\r\n\t\t\treturn _Math.RAD2DEG * 2 * Math.atan(\r\n\t\t\t\tMath.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom );\r\n\r\n\t\t},\r\n\r\n\t\tgetFilmWidth: function () {\r\n\r\n\t\t\t// film not completely covered in portrait format (aspect < 1)\r\n\t\t\treturn this.filmGauge * Math.min( this.aspect, 1 );\r\n\r\n\t\t},\r\n\r\n\t\tgetFilmHeight: function () {\r\n\r\n\t\t\t// film not completely covered in landscape format (aspect > 1)\r\n\t\t\treturn this.filmGauge / Math.max( this.aspect, 1 );\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Sets an offset in a larger frustum. This is useful for multi-window or\r\n\t\t * multi-monitor/multi-machine setups.\r\n\t\t *\r\n\t\t * For example, if you have 3x2 monitors and each monitor is 1920x1080 and\r\n\t\t * the monitors are in grid like this\r\n\t\t *\r\n\t\t * +---+---+---+\r\n\t\t * | A | B | C |\r\n\t\t * +---+---+---+\r\n\t\t * | D | E | F |\r\n\t\t * +---+---+---+\r\n\t\t *\r\n\t\t * then for each monitor you would call it like this\r\n\t\t *\r\n\t\t * var w = 1920;\r\n\t\t * var h = 1080;\r\n\t\t * var fullWidth = w * 3;\r\n\t\t * var fullHeight = h * 2;\r\n\t\t *\r\n\t\t * --A--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );\r\n\t\t * --B--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );\r\n\t\t * --C--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );\r\n\t\t * --D--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );\r\n\t\t * --E--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );\r\n\t\t * --F--\r\n\t\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );\r\n\t\t *\r\n\t\t * Note there is no reason monitors have to be the same size or in a grid.\r\n\t\t */\r\n\t\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\r\n\r\n\t\t\tthis.aspect = fullWidth / fullHeight;\r\n\r\n\t\t\tif ( this.view === null ) {\r\n\r\n\t\t\t\tthis.view = {\r\n\t\t\t\t\tenabled: true,\r\n\t\t\t\t\tfullWidth: 1,\r\n\t\t\t\t\tfullHeight: 1,\r\n\t\t\t\t\toffsetX: 0,\r\n\t\t\t\t\toffsetY: 0,\r\n\t\t\t\t\twidth: 1,\r\n\t\t\t\t\theight: 1\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.view.enabled = true;\r\n\t\t\tthis.view.fullWidth = fullWidth;\r\n\t\t\tthis.view.fullHeight = fullHeight;\r\n\t\t\tthis.view.offsetX = x;\r\n\t\t\tthis.view.offsetY = y;\r\n\t\t\tthis.view.width = width;\r\n\t\t\tthis.view.height = height;\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tclearViewOffset: function () {\r\n\r\n\t\t\tif ( this.view !== null ) {\r\n\r\n\t\t\t\tthis.view.enabled = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tupdateProjectionMatrix: function () {\r\n\r\n\t\t\tvar near = this.near,\r\n\t\t\t\ttop = near * Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom,\r\n\t\t\t\theight = 2 * top,\r\n\t\t\t\twidth = this.aspect * height,\r\n\t\t\t\tleft = - 0.5 * width,\r\n\t\t\t\tview = this.view;\r\n\r\n\t\t\tif ( this.view !== null && this.view.enabled ) {\r\n\r\n\t\t\t\tvar fullWidth = view.fullWidth,\r\n\t\t\t\t\tfullHeight = view.fullHeight;\r\n\r\n\t\t\t\tleft += view.offsetX * width / fullWidth;\r\n\t\t\t\ttop -= view.offsetY * height / fullHeight;\r\n\t\t\t\twidth *= view.width / fullWidth;\r\n\t\t\t\theight *= view.height / fullHeight;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar skew = this.filmOffset;\r\n\t\t\tif ( skew !== 0 ) { left += near * skew / this.getFilmWidth(); }\r\n\r\n\t\t\tthis.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );\r\n\r\n\t\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.fov = this.fov;\r\n\t\t\tdata.object.zoom = this.zoom;\r\n\r\n\t\t\tdata.object.near = this.near;\r\n\t\t\tdata.object.far = this.far;\r\n\t\t\tdata.object.focus = this.focus;\r\n\r\n\t\t\tdata.object.aspect = this.aspect;\r\n\r\n\t\t\tif ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); }\r\n\r\n\t\t\tdata.object.filmGauge = this.filmGauge;\r\n\t\t\tdata.object.filmOffset = this.filmOffset;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * Camera for rendering cube maps\r\n\t *\t- renders scene into axis-aligned cube\r\n\t *\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar fov = 90, aspect = 1;\r\n\r\n\tfunction CubeCamera( near, far, cubeResolution, options ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'CubeCamera';\r\n\r\n\t\tvar cameraPX = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPX.up.set( 0, - 1, 0 );\r\n\t\tcameraPX.lookAt( new Vector3( 1, 0, 0 ) );\r\n\t\tthis.add( cameraPX );\r\n\r\n\t\tvar cameraNX = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNX.up.set( 0, - 1, 0 );\r\n\t\tcameraNX.lookAt( new Vector3( - 1, 0, 0 ) );\r\n\t\tthis.add( cameraNX );\r\n\r\n\t\tvar cameraPY = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPY.up.set( 0, 0, 1 );\r\n\t\tcameraPY.lookAt( new Vector3( 0, 1, 0 ) );\r\n\t\tthis.add( cameraPY );\r\n\r\n\t\tvar cameraNY = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNY.up.set( 0, 0, - 1 );\r\n\t\tcameraNY.lookAt( new Vector3( 0, - 1, 0 ) );\r\n\t\tthis.add( cameraNY );\r\n\r\n\t\tvar cameraPZ = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraPZ.up.set( 0, - 1, 0 );\r\n\t\tcameraPZ.lookAt( new Vector3( 0, 0, 1 ) );\r\n\t\tthis.add( cameraPZ );\r\n\r\n\t\tvar cameraNZ = new PerspectiveCamera( fov, aspect, near, far );\r\n\t\tcameraNZ.up.set( 0, - 1, 0 );\r\n\t\tcameraNZ.lookAt( new Vector3( 0, 0, - 1 ) );\r\n\t\tthis.add( cameraNZ );\r\n\r\n\t\toptions = options || { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter };\r\n\r\n\t\tthis.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options );\r\n\t\tthis.renderTarget.texture.name = \"CubeCamera\";\r\n\r\n\t\tthis.update = function ( renderer, scene ) {\r\n\r\n\t\t\tif ( this.parent === null ) { this.updateMatrixWorld(); }\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\r\n\t\t\tvar renderTarget = this.renderTarget;\r\n\t\t\tvar generateMipmaps = renderTarget.texture.generateMipmaps;\r\n\r\n\t\t\trenderTarget.texture.generateMipmaps = false;\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 0 );\r\n\t\t\trenderer.render( scene, cameraPX );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 1 );\r\n\t\t\trenderer.render( scene, cameraNX );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 2 );\r\n\t\t\trenderer.render( scene, cameraPY );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 3 );\r\n\t\t\trenderer.render( scene, cameraNY );\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 4 );\r\n\t\t\trenderer.render( scene, cameraPZ );\r\n\r\n\t\t\trenderTarget.texture.generateMipmaps = generateMipmaps;\r\n\r\n\t\t\trenderer.setRenderTarget( renderTarget, 5 );\r\n\t\t\trenderer.render( scene, cameraNZ );\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clear = function ( renderer, color, depth, stencil ) {\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\r\n\t\t\tvar renderTarget = this.renderTarget;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\trenderer.setRenderTarget( renderTarget, i );\r\n\r\n\t\t\t\trenderer.clear( color, depth, stencil );\r\n\r\n\t\t\t}\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tCubeCamera.prototype = Object.create( Object3D.prototype );\r\n\tCubeCamera.prototype.constructor = CubeCamera;\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction WebGLRenderTargetCube( width, height, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t}\r\n\r\n\tWebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype );\r\n\tWebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube;\r\n\r\n\tWebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true;\r\n\r\n\tWebGLRenderTargetCube.prototype.fromEquirectangularTexture = function ( renderer, texture ) {\r\n\r\n\t\tthis.texture.type = texture.type;\r\n\t\tthis.texture.format = texture.format;\r\n\t\tthis.texture.encoding = texture.encoding;\r\n\r\n\t\tvar scene = new Scene();\r\n\r\n\t\tvar shader = {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\ttEquirect: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: [\r\n\r\n\t\t\t\t\"varying vec3 vWorldDirection;\",\r\n\r\n\t\t\t\t\"vec3 transformDirection( in vec3 dir, in mat4 matrix ) {\",\r\n\r\n\t\t\t\t\"\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\",\r\n\r\n\t\t\t\t\"}\",\r\n\r\n\t\t\t\t\"void main() {\",\r\n\r\n\t\t\t\t\"\tvWorldDirection = transformDirection( position, modelMatrix );\",\r\n\r\n\t\t\t\t\"\t#include \",\r\n\t\t\t\t\"\t#include \",\r\n\r\n\t\t\t\t\"}\"\r\n\r\n\t\t\t].join( '\\n' ),\r\n\r\n\t\t\tfragmentShader: [\r\n\r\n\t\t\t\t\"uniform sampler2D tEquirect;\",\r\n\r\n\t\t\t\t\"varying vec3 vWorldDirection;\",\r\n\r\n\t\t\t\t\"#define RECIPROCAL_PI 0.31830988618\",\r\n\t\t\t\t\"#define RECIPROCAL_PI2 0.15915494\",\r\n\r\n\t\t\t\t\"void main() {\",\r\n\r\n\t\t\t\t\"\tvec3 direction = normalize( vWorldDirection );\",\r\n\r\n\t\t\t\t\"\tvec2 sampleUV;\",\r\n\r\n\t\t\t\t\"\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\",\r\n\r\n\t\t\t\t\"\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\",\r\n\r\n\t\t\t\t\"\tgl_FragColor = texture2D( tEquirect, sampleUV );\",\r\n\r\n\t\t\t\t\"}\"\r\n\r\n\t\t\t].join( '\\n' ),\r\n\t\t};\r\n\r\n\t\tvar material = new ShaderMaterial( {\r\n\r\n\t\t\ttype: 'CubemapFromEquirect',\r\n\r\n\t\t\tuniforms: cloneUniforms( shader.uniforms ),\r\n\t\t\tvertexShader: shader.vertexShader,\r\n\t\t\tfragmentShader: shader.fragmentShader,\r\n\t\t\tside: BackSide,\r\n\t\t\tblending: NoBlending\r\n\r\n\t\t} );\r\n\r\n\t\tmaterial.uniforms.tEquirect.value = texture;\r\n\r\n\t\tvar mesh = new Mesh( new BoxBufferGeometry( 5, 5, 5 ), material );\r\n\r\n\t\tscene.add( mesh );\r\n\r\n\t\tvar camera = new CubeCamera( 1, 10, 1 );\r\n\r\n\t\tcamera.renderTarget = this;\r\n\t\tcamera.renderTarget.texture.name = 'CubeCameraTexture';\r\n\r\n\t\tcamera.update( renderer, scene );\r\n\r\n\t\tmesh.geometry.dispose();\r\n\t\tmesh.material.dispose();\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1 };\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\t\tthis.unpackAlignment = 1;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tDataTexture.prototype = Object.create( Texture.prototype );\r\n\tDataTexture.prototype.constructor = DataTexture;\r\n\r\n\tDataTexture.prototype.isDataTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _sphere$1 = new Sphere();\r\n\tvar _vector$6 = new Vector3();\r\n\r\n\tfunction Frustum( p0, p1, p2, p3, p4, p5 ) {\r\n\r\n\t\tthis.planes = [\r\n\r\n\t\t\t( p0 !== undefined ) ? p0 : new Plane(),\r\n\t\t\t( p1 !== undefined ) ? p1 : new Plane(),\r\n\t\t\t( p2 !== undefined ) ? p2 : new Plane(),\r\n\t\t\t( p3 !== undefined ) ? p3 : new Plane(),\r\n\t\t\t( p4 !== undefined ) ? p4 : new Plane(),\r\n\t\t\t( p5 !== undefined ) ? p5 : new Plane()\r\n\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tObject.assign( Frustum.prototype, {\r\n\r\n\t\tset: function ( p0, p1, p2, p3, p4, p5 ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tplanes[ 0 ].copy( p0 );\r\n\t\t\tplanes[ 1 ].copy( p1 );\r\n\t\t\tplanes[ 2 ].copy( p2 );\r\n\t\t\tplanes[ 3 ].copy( p3 );\r\n\t\t\tplanes[ 4 ].copy( p4 );\r\n\t\t\tplanes[ 5 ].copy( p5 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( frustum ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tplanes[ i ].copy( frustum.planes[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromMatrix: function ( m ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\t\t\tvar me = m.elements;\r\n\t\t\tvar me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];\r\n\t\t\tvar me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];\r\n\t\t\tvar me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];\r\n\t\t\tvar me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];\r\n\r\n\t\t\tplanes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();\r\n\t\t\tplanes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();\r\n\t\t\tplanes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();\r\n\t\t\tplanes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();\r\n\t\t\tplanes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();\r\n\t\t\tplanes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsObject: function ( object ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$1.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );\r\n\r\n\t\t\treturn this.intersectsSphere( _sphere$1 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSprite: function ( sprite ) {\r\n\r\n\t\t\t_sphere$1.center.set( 0, 0, 0 );\r\n\t\t\t_sphere$1.radius = 0.7071067811865476;\r\n\t\t\t_sphere$1.applyMatrix4( sprite.matrixWorld );\r\n\r\n\t\t\treturn this.intersectsSphere( _sphere$1 );\r\n\r\n\t\t},\r\n\r\n\t\tintersectsSphere: function ( sphere ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\t\t\tvar center = sphere.center;\r\n\t\t\tvar negRadius = - sphere.radius;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tvar distance = planes[ i ].distanceToPoint( center );\r\n\r\n\t\t\t\tif ( distance < negRadius ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tvar plane = planes[ i ];\r\n\r\n\t\t\t\t// corner at max distance\r\n\r\n\t\t\t\t_vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x;\r\n\t\t\t\t_vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y;\r\n\t\t\t\t_vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z;\r\n\r\n\t\t\t\tif ( plane.distanceToPoint( _vector$6 ) < 0 ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\tvar planes = this.planes;\r\n\r\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\tif ( planes[ i ].distanceToPoint( point ) < 0 ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar alphamap_fragment = \"#ifdef USE_ALPHAMAP\\n\\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\\n#endif\";\n\n\tvar alphamap_pars_fragment = \"#ifdef USE_ALPHAMAP\\n\\tuniform sampler2D alphaMap;\\n#endif\";\n\n\tvar alphatest_fragment = \"#ifdef ALPHATEST\\n\\tif ( diffuseColor.a < ALPHATEST ) discard;\\n#endif\";\n\n\tvar 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( STANDARD )\\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\n\tvar aomap_pars_fragment = \"#ifdef USE_AOMAP\\n\\tuniform sampler2D aoMap;\\n\\tuniform float aoMapIntensity;\\n#endif\";\n\n\tvar begin_vertex = \"vec3 transformed = vec3( position );\";\n\n\tvar beginnormal_vertex = \"vec3 objectNormal = vec3( normal );\\n#ifdef USE_TANGENT\\n\\tvec3 objectTangent = vec3( tangent.xyz );\\n#endif\";\n\n\tvar bsdfs = \"vec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\\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\\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\\n}\\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\\n\\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\\n\\tif( cutoffDistance > 0.0 ) {\\n\\t\\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\\n\\t}\\n\\treturn distanceFalloff;\\n#else\\n\\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\\n\\t\\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\\n\\t}\\n\\treturn 1.0;\\n#endif\\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}\\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\\n\\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\\n\\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\\n\\treturn Fr * fresnel + F0;\\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 vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\\n\\tfloat alpha = pow2( roughness );\\n\\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\\n\\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\\n\\tfloat dotNV = saturate( dot( normal, viewDir ) );\\n\\tfloat dotNH = saturate( dot( 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 dotNV = saturate( dot( N, V ) );\\n\\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\\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.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\\n\\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\\n\\tfloat v = a / b;\\n\\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - 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\\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\\n\\treturn vec3( result );\\n}\\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\\n\\tfloat dotNV = saturate( dot( normal, viewDir ) );\\n\\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\\n\\treturn specularColor * brdf.x + brdf.y;\\n}\\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\\n\\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\\n\\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\\n\\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\\n\\tvec3 FssEss = F * brdf.x + brdf.y;\\n\\tfloat Ess = brdf.x + brdf.y;\\n\\tfloat Ems = 1.0 - Ess;\\n\\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\\n\\tsingleScatter += FssEss;\\n\\tmultiScatter += Fms * Ems;\\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#if defined( USE_SHEEN )\\nfloat D_Charlie(float roughness, float NoH) {\\n\\tfloat invAlpha = 1.0 / roughness;\\n\\tfloat cos2h = NoH * NoH;\\n\\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\\n}\\nfloat V_Neubelt(float NoV, float NoL) {\\n\\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\\n}\\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\\n\\tvec3 N = geometry.normal;\\n\\tvec3 V = geometry.viewDir;\\n\\tvec3 H = normalize( V + L );\\n\\tfloat dotNH = saturate( dot( N, H ) );\\n\\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\\n}\\n#endif\";\n\n\tvar 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\\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\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\n\tvar clipping_planes_fragment = \"#if NUM_CLIPPING_PLANES > 0\\n\\tvec4 plane;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\\n\\t\\tplane = clippingPlanes[ i ];\\n\\t\\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\\n\\t}\\n\\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\\n\\t\\tbool clipped = true;\\n\\t\\t#pragma unroll_loop\\n\\t\\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\\n\\t\\t\\tplane = clippingPlanes[ i ];\\n\\t\\t\\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\\n\\t\\t}\\n\\t\\tif ( clipped ) discard;\\n\\t#endif\\n#endif\";\n\n\tvar clipping_planes_pars_fragment = \"#if NUM_CLIPPING_PLANES > 0\\n\\t#if ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\t\\tvarying vec3 vViewPosition;\\n\\t#endif\\n\\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\\n#endif\";\n\n\tvar clipping_planes_pars_vertex = \"#if NUM_CLIPPING_PLANES > 0 && ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\";\n\n\tvar clipping_planes_vertex = \"#if NUM_CLIPPING_PLANES > 0 && ! defined( STANDARD ) && ! defined( PHONG ) && ! defined( MATCAP )\\n\\tvViewPosition = - mvPosition.xyz;\\n#endif\";\n\n\tvar color_fragment = \"#ifdef USE_COLOR\\n\\tdiffuseColor.rgb *= vColor;\\n#endif\";\n\n\tvar color_pars_fragment = \"#ifdef USE_COLOR\\n\\tvarying vec3 vColor;\\n#endif\";\n\n\tvar color_pars_vertex = \"#ifdef USE_COLOR\\n\\tvarying vec3 vColor;\\n#endif\";\n\n\tvar color_vertex = \"#ifdef USE_COLOR\\n\\tvColor.xyz = color.xyz;\\n#endif\";\n\n\tvar 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#ifndef saturate\\n#define saturate(a) clamp( a, 0.0, 1.0 )\\n#endif\\n#define whiteComplement(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}\\n#ifdef HIGH_PRECISION\\n\\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\\n#else\\n\\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\\n\\tfloat precisionSafeLength( vec3 v ) {\\n\\t\\tfloat maxComponent = max3( abs( v ) );\\n\\t\\treturn length( v / maxComponent ) * maxComponent;\\n\\t}\\n#endif\\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#ifdef CLEARCOAT\\n\\tvec3 clearcoatNormal;\\n#endif\\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}\\nbool isPerspectiveMatrix( mat4 m ) {\\n return m[ 2 ][ 3 ] == - 1.0;\\n}\";\n\n\tvar cube_uv_reflection_fragment = \"#ifdef ENVMAP_TYPE_CUBE_UV\\n#define cubeUV_maxMipLevel 8.0\\n#define cubeUV_minMipLevel 4.0\\n#define cubeUV_maxTileSize 256.0\\n#define cubeUV_minTileSize 16.0\\nfloat getFace(vec3 direction) {\\n vec3 absDirection = abs(direction);\\n float face = -1.0;\\n if (absDirection.x > absDirection.z) {\\n if (absDirection.x > absDirection.y)\\n face = direction.x > 0.0 ? 0.0 : 3.0;\\n else\\n face = direction.y > 0.0 ? 1.0 : 4.0;\\n } else {\\n if (absDirection.z > absDirection.y)\\n face = direction.z > 0.0 ? 2.0 : 5.0;\\n else\\n face = direction.y > 0.0 ? 1.0 : 4.0;\\n }\\n return face;\\n}\\nvec2 getUV(vec3 direction, float face) {\\n vec2 uv;\\n if (face == 0.0) {\\n uv = vec2(-direction.z, direction.y) / abs(direction.x);\\n } else if (face == 1.0) {\\n uv = vec2(direction.x, -direction.z) / abs(direction.y);\\n } else if (face == 2.0) {\\n uv = direction.xy / abs(direction.z);\\n } else if (face == 3.0) {\\n uv = vec2(direction.z, direction.y) / abs(direction.x);\\n } else if (face == 4.0) {\\n uv = direction.xz / abs(direction.y);\\n } else {\\n uv = vec2(-direction.x, direction.y) / abs(direction.z);\\n }\\n return 0.5 * (uv + 1.0);\\n}\\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\\n float face = getFace(direction);\\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\\n mipInt = max(mipInt, cubeUV_minMipLevel);\\n float faceSize = exp2(mipInt);\\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\\n vec2 f = fract(uv);\\n uv += 0.5 - f;\\n if (face > 2.0) {\\n uv.y += faceSize;\\n face -= 3.0;\\n }\\n uv.x += face * faceSize;\\n if(mipInt < cubeUV_maxMipLevel){\\n uv.y += 2.0 * cubeUV_maxTileSize;\\n }\\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\\n uv *= texelSize;\\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.x += texelSize;\\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.y += texelSize;\\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n uv.x -= texelSize;\\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\\n vec3 tm = mix(tl, tr, f.x);\\n vec3 bm = mix(bl, br, f.x);\\n return mix(tm, bm, f.y);\\n}\\n#define r0 1.0\\n#define v0 0.339\\n#define m0 -2.0\\n#define r1 0.8\\n#define v1 0.276\\n#define m1 -1.0\\n#define r4 0.4\\n#define v4 0.046\\n#define m4 2.0\\n#define r5 0.305\\n#define v5 0.016\\n#define m5 3.0\\n#define r6 0.21\\n#define v6 0.0038\\n#define m6 4.0\\nfloat roughnessToVariance(float roughness) {\\n float variance = 0.0;\\n if (roughness >= r1) {\\n variance = (r0 - roughness) * (v1 - v0) / (r0 - r1) + v0;\\n } else if (roughness >= r4) {\\n variance = (r1 - roughness) * (v4 - v1) / (r1 - r4) + v1;\\n } else if (roughness >= r5) {\\n variance = (r4 - roughness) * (v5 - v4) / (r4 - r5) + v4;\\n } else {\\n float roughness2 = roughness * roughness;\\n variance = 1.79 * roughness2 * roughness2;\\n }\\n return variance;\\n}\\nfloat varianceToRoughness(float variance) {\\n float roughness = 0.0;\\n if (variance >= v1) {\\n roughness = (v0 - variance) * (r1 - r0) / (v0 - v1) + r0;\\n } else if (variance >= v4) {\\n roughness = (v1 - variance) * (r4 - r1) / (v1 - v4) + r1;\\n } else if (variance >= v5) {\\n roughness = (v4 - variance) * (r5 - r4) / (v4 - v5) + r4;\\n } else {\\n roughness = pow(0.559 * variance, 0.25); }\\n return roughness;\\n}\\nfloat roughnessToMip(float roughness) {\\n float mip = 0.0;\\n if (roughness >= r1) {\\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\\n } else if (roughness >= r4) {\\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\\n } else if (roughness >= r5) {\\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\\n } else if (roughness >= r6) {\\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\\n } else {\\n mip = -2.0 * log2(1.16 * roughness); }\\n return mip;\\n}\\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\\n float mipF = fract(mip);\\n float mipInt = floor(mip);\\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\\n if (mipF == 0.0) {\\n return vec4(color0, 1.0);\\n } else {\\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\\n return vec4(mix(color0, color1, mipF), 1.0);\\n }\\n}\\n#endif\";\n\n\tvar defaultnormal_vertex = \"vec3 transformedNormal = objectNormal;\\n#ifdef USE_INSTANCING\\n\\ttransformedNormal = mat3( instanceMatrix ) * transformedNormal;\\n#endif\\ntransformedNormal = normalMatrix * transformedNormal;\\n#ifdef FLIP_SIDED\\n\\ttransformedNormal = - transformedNormal;\\n#endif\\n#ifdef USE_TANGENT\\n\\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\\n\\t#ifdef FLIP_SIDED\\n\\t\\ttransformedTangent = - transformedTangent;\\n\\t#endif\\n#endif\";\n\n\tvar displacementmap_pars_vertex = \"#ifdef USE_DISPLACEMENTMAP\\n\\tuniform sampler2D displacementMap;\\n\\tuniform float displacementScale;\\n\\tuniform float displacementBias;\\n#endif\";\n\n\tvar displacementmap_vertex = \"#ifdef USE_DISPLACEMENTMAP\\n\\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\\n#endif\";\n\n\tvar emissivemap_fragment = \"#ifdef USE_EMISSIVEMAP\\n\\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\\n\\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\\n\\ttotalEmissiveRadiance *= emissiveColor.rgb;\\n#endif\";\n\n\tvar emissivemap_pars_fragment = \"#ifdef USE_EMISSIVEMAP\\n\\tuniform sampler2D emissiveMap;\\n#endif\";\n\n\tvar encodings_fragment = \"gl_FragColor = linearToOutputTexel( gl_FragColor );\";\n\n\tvar 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.rgb, vec3( gammaFactor ) ), value.a );\\n}\\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\\n\\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\\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.a );\\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.a );\\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.rgb * value.a * maxRange, 1.0 );\\n}\\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\\n\\tfloat maxRGB = max( value.r, 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.r, 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 = cLogLuvM * value.rgb;\\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 = cLogLuvInverseM * Xp_Y_XYZp.rgb;\\n\\treturn vec4( max( vRGB, 0.0 ), 1.0 );\\n}\";\n\n\tvar envmap_fragment = \"#ifdef USE_ENVMAP\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvec3 cameraToFrag;\\n\\t\\t\\n\\t\\tif ( isOrthographic ) {\\n\\t\\t\\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\\n\\t\\t} else {\\n\\t\\t\\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\\n\\t\\t}\\n\\t\\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\\n\\t\\t#ifdef ENVMAP_MODE_REFLECTION\\n\\t\\t\\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\\n\\t\\t#else\\n\\t\\t\\tvec3 reflectVec = refract( cameraToFrag, 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_CUBE_UV )\\n\\t\\tvec4 envColor = textureCubeUV( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ), 0.0 );\\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\\t#ifndef ENVMAP_TYPE_CUBE_UV\\n\\t\\tenvColor = envMapTexelToLinear( envColor );\\n\\t#endif\\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\n\tvar envmap_common_pars_fragment = \"#ifdef USE_ENVMAP\\n\\tuniform float envMapIntensity;\\n\\tuniform float flipEnvMap;\\n\\tuniform int maxMipLevel;\\n\\t#ifdef ENVMAP_TYPE_CUBE\\n\\t\\tuniform samplerCube envMap;\\n\\t#else\\n\\t\\tuniform sampler2D envMap;\\n\\t#endif\\n\\t\\n#endif\";\n\n\tvar envmap_pars_fragment = \"#ifdef USE_ENVMAP\\n\\tuniform float reflectivity;\\n\\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\\n\\t\\t#define ENV_WORLDPOS\\n\\t#endif\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvarying vec3 vWorldPosition;\\n\\t\\tuniform float refractionRatio;\\n\\t#else\\n\\t\\tvarying vec3 vReflect;\\n\\t#endif\\n#endif\";\n\n\tvar envmap_pars_vertex = \"#ifdef USE_ENVMAP\\n\\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\\n\\t\\t#define ENV_WORLDPOS\\n\\t#endif\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\t\\n\\t\\tvarying vec3 vWorldPosition;\\n\\t#else\\n\\t\\tvarying vec3 vReflect;\\n\\t\\tuniform float refractionRatio;\\n\\t#endif\\n#endif\";\n\n\tvar envmap_vertex = \"#ifdef USE_ENVMAP\\n\\t#ifdef ENV_WORLDPOS\\n\\t\\tvWorldPosition = worldPosition.xyz;\\n\\t#else\\n\\t\\tvec3 cameraToVertex;\\n\\t\\tif ( isOrthographic ) { \\n\\t\\t\\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\\n\\t\\t} else {\\n\\t\\t\\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\\n\\t\\t}\\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\n\tvar fog_vertex = \"#ifdef USE_FOG\\n\\tfogDepth = -mvPosition.z;\\n#endif\";\n\n\tvar fog_pars_vertex = \"#ifdef USE_FOG\\n\\tvarying float fogDepth;\\n#endif\";\n\n\tvar fog_fragment = \"#ifdef USE_FOG\\n\\t#ifdef FOG_EXP2\\n\\t\\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\\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\n\tvar 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\n\tvar gradientmap_pars_fragment = \"#ifdef USE_GRADIENTMAP\\n\\tuniform sampler2D gradientMap;\\n#endif\\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\\n\\tfloat dotNL = dot( normal, lightDirection );\\n\\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\\n\\t#ifdef USE_GRADIENTMAP\\n\\t\\treturn texture2D( gradientMap, coord ).rgb;\\n\\t#else\\n\\t\\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\\n\\t#endif\\n}\";\n\n\tvar lightmap_fragment = \"#ifdef USE_LIGHTMAP\\n\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\\n#endif\";\n\n\tvar lightmap_pars_fragment = \"#ifdef USE_LIGHTMAP\\n\\tuniform sampler2D lightMap;\\n\\tuniform float lightMapIntensity;\\n#endif\";\n\n\tvar lights_lambert_vertex = \"vec3 diffuse = vec3( 1.0 );\\nGeometricContext geometry;\\ngeometry.position = mvPosition.xyz;\\ngeometry.normal = normalize( transformedNormal );\\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\\nGeometricContext backGeometry;\\nbackGeometry.position = geometry.position;\\nbackGeometry.normal = -geometry.normal;\\nbackGeometry.viewDir = geometry.viewDir;\\nvLightFront = vec3( 0.0 );\\nvIndirectFront = vec3( 0.0 );\\n#ifdef DOUBLE_SIDED\\n\\tvLightBack = vec3( 0.0 );\\n\\tvIndirectBack = vec3( 0.0 );\\n#endif\\nIncidentLight directLight;\\nfloat dotNL;\\nvec3 directLightColor_Diffuse;\\n#if NUM_POINT_LIGHTS > 0\\n\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\\n\\t\\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\\n\\t\\t#ifdef DOUBLE_SIDED\\n\\t\\t\\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\\n\\t\\t#endif\\n\\t}\\n#endif\";\n\n\tvar lights_pars_begin = \"uniform bool receiveShadow;\\nuniform vec3 ambientLightColor;\\nuniform vec3 lightProbe[ 9 ];\\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\\n\\tfloat x = normal.x, y = normal.y, z = normal.z;\\n\\tvec3 result = shCoefficients[ 0 ] * 0.886227;\\n\\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\\n\\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\\n\\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\\n\\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\\n\\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\\n\\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\\n\\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\\n\\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\\n\\treturn result;\\n}\\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\\n\\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\\n\\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\\n\\treturn irradiance;\\n}\\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 ltc_1;\\tuniform sampler2D ltc_2;\\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\n\tvar envmap_physical_pars_fragment = \"#if defined( USE_ENVMAP )\\n\\t#ifdef ENVMAP_MODE_REFRACTION\\n\\t\\tuniform float refractionRatio;\\n\\t#endif\\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( envMap, 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 roughness, const in int maxMIPLevel ) {\\n\\t\\tfloat maxMIPLevelScalar = float( maxMIPLevel );\\n\\t\\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\\n\\t\\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\\n\\t\\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\\n\\t}\\n\\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\\n\\t\\t#ifdef ENVMAP_MODE_REFLECTION\\n\\t\\t vec3 reflectVec = reflect( -viewDir, normal );\\n\\t\\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\\n\\t\\t#else\\n\\t\\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\\n\\t\\t#endif\\n\\t\\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\\n\\t\\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, 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( envMap, queryReflectVec, roughness );\\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\n\tvar lights_toon_fragment = \"ToonMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb;\\nmaterial.specularColor = specular;\\nmaterial.specularShininess = shininess;\\nmaterial.specularStrength = specularStrength;\";\n\n\tvar lights_toon_pars_fragment = \"varying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\nstruct ToonMaterial {\\n\\tvec3\\tdiffuseColor;\\n\\tvec3\\tspecularColor;\\n\\tfloat\\tspecularShininess;\\n\\tfloat\\tspecularStrength;\\n};\\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\\n\\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\\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_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\\n\\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\\n}\\n#define RE_Direct\\t\\t\\t\\tRE_Direct_Toon\\n#define RE_IndirectDiffuse\\t\\tRE_IndirectDiffuse_Toon\\n#define Material_LightProbeLOD( material )\\t(0)\";\n\n\tvar lights_phong_fragment = \"BlinnPhongMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb;\\nmaterial.specularColor = specular;\\nmaterial.specularShininess = shininess;\\nmaterial.specularStrength = specularStrength;\";\n\n\tvar 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\\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\\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\n\tvar lights_physical_fragment = \"PhysicalMaterial material;\\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\\n#ifdef REFLECTIVITY\\n\\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\\n#else\\n\\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\\n#endif\\n#ifdef CLEARCOAT\\n\\tmaterial.clearcoat = saturate( clearcoat );\\tmaterial.clearcoatRoughness = max( clearcoatRoughness, 0.0525 );\\n\\tmaterial.clearcoatRoughness += geometryRoughness;\\n\\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\\n#endif\\n#ifdef USE_SHEEN\\n\\tmaterial.sheenColor = sheen;\\n#endif\";\n\n\tvar lights_physical_pars_fragment = \"struct PhysicalMaterial {\\n\\tvec3\\tdiffuseColor;\\n\\tfloat\\tspecularRoughness;\\n\\tvec3\\tspecularColor;\\n#ifdef CLEARCOAT\\n\\tfloat clearcoat;\\n\\tfloat clearcoatRoughness;\\n#endif\\n#ifdef USE_SHEEN\\n\\tvec3 sheenColor;\\n#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\\tvec4 t1 = texture2D( ltc_1, uv );\\n\\t\\tvec4 t2 = texture2D( ltc_2, uv );\\n\\t\\tmat3 mInv = mat3(\\n\\t\\t\\tvec3( t1.x, 0, t1.y ),\\n\\t\\t\\tvec3( 0, 1, 0 ),\\n\\t\\t\\tvec3( t1.z, 0, t1.w )\\n\\t\\t);\\n\\t\\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\\n\\t\\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\\n\\t\\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), 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#ifdef CLEARCOAT\\n\\t\\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\\n\\t\\tvec3 ccIrradiance = ccDotNL * directLight.color;\\n\\t\\t#ifndef PHYSICALLY_CORRECT_LIGHTS\\n\\t\\t\\tccIrradiance *= PI;\\n\\t\\t#endif\\n\\t\\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\\n\\t\\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\\n\\t#else\\n\\t\\tfloat clearcoatDHR = 0.0;\\n\\t#endif\\n\\t#ifdef USE_SHEEN\\n\\t\\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\\n\\t\\t\\tmaterial.specularRoughness,\\n\\t\\t\\tdirectLight.direction,\\n\\t\\t\\tgeometry,\\n\\t\\t\\tmaterial.sheenColor\\n\\t\\t);\\n\\t#else\\n\\t\\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\\n\\t#endif\\n\\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\\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 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\\n\\t#ifdef CLEARCOAT\\n\\t\\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\\n\\t\\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\\n\\t\\tfloat ccDotNL = ccDotNV;\\n\\t\\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\\n\\t#else\\n\\t\\tfloat clearcoatDHR = 0.0;\\n\\t#endif\\n\\tfloat clearcoatInv = 1.0 - clearcoatDHR;\\n\\tvec3 singleScattering = vec3( 0.0 );\\n\\tvec3 multiScattering = vec3( 0.0 );\\n\\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\\n\\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\\n\\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\\n\\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\\n\\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\\n\\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\\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\\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\n\tvar lights_fragment_begin = \"\\nGeometricContext geometry;\\ngeometry.position = - vViewPosition;\\ngeometry.normal = normal;\\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\\n#ifdef CLEARCOAT\\n\\tgeometry.clearcoatNormal = clearcoatNormal;\\n#endif\\nIncidentLight directLight;\\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\\n\\tPointLight pointLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\\n\\t\\tpointLight = pointLights[ i ];\\n\\t\\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( pointLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\\n\\t\\tspotLight = spotLights[ i ];\\n\\t\\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( spotLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\\n\\t\\tdirectionalLight = directionalLights[ i ];\\n\\t\\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\\n\\t\\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\\n\\t\\tdirectLight.color *= all( bvec3( directionalLight.shadow, directLight.visible, receiveShadow ) ) ? 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\\t#pragma unroll_loop\\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 iblIrradiance = vec3( 0.0 );\\n\\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\\n\\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\\n\\t#if ( NUM_HEMI_LIGHTS > 0 )\\n\\t\\t#pragma unroll_loop\\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#endif\\n#if defined( RE_IndirectSpecular )\\n\\tvec3 radiance = vec3( 0.0 );\\n\\tvec3 clearcoatRadiance = vec3( 0.0 );\\n#endif\";\n\n\tvar lights_fragment_maps = \"#if defined( RE_IndirectDiffuse )\\n\\t#ifdef USE_LIGHTMAP\\n\\t\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\t\\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * 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 defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\\n\\t\\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\\n\\t#endif\\n#endif\\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\\n\\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\\n\\t#ifdef CLEARCOAT\\n\\t\\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\\n\\t#endif\\n#endif\";\n\n\tvar lights_fragment_end = \"#if defined( RE_IndirectDiffuse )\\n\\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\\n#endif\\n#if defined( RE_IndirectSpecular )\\n\\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\\n#endif\";\n\n\tvar logdepthbuf_fragment = \"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\\n\\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\\n#endif\";\n\n\tvar logdepthbuf_pars_fragment = \"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\\n\\tuniform float logDepthBufFC;\\n\\tvarying float vFragDepth;\\n\\tvarying float vIsPerspective;\\n#endif\";\n\n\tvar logdepthbuf_pars_vertex = \"#ifdef USE_LOGDEPTHBUF\\n\\t#ifdef USE_LOGDEPTHBUF_EXT\\n\\t\\tvarying float vFragDepth;\\n\\t\\tvarying float vIsPerspective;\\n\\t#else\\n\\t\\tuniform float logDepthBufFC;\\n\\t#endif\\n#endif\";\n\n\tvar logdepthbuf_vertex = \"#ifdef USE_LOGDEPTHBUF\\n\\t#ifdef USE_LOGDEPTHBUF_EXT\\n\\t\\tvFragDepth = 1.0 + gl_Position.w;\\n\\t\\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\\n\\t#else\\n\\t\\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\\n\\t\\t\\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\\n\\t\\t\\tgl_Position.z *= gl_Position.w;\\n\\t\\t}\\n\\t#endif\\n#endif\";\n\n\tvar map_fragment = \"#ifdef USE_MAP\\n\\tvec4 texelColor = texture2D( map, vUv );\\n\\ttexelColor = mapTexelToLinear( texelColor );\\n\\tdiffuseColor *= texelColor;\\n#endif\";\n\n\tvar map_pars_fragment = \"#ifdef USE_MAP\\n\\tuniform sampler2D map;\\n#endif\";\n\n\tvar map_particle_fragment = \"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\\n\\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\\n#endif\\n#ifdef USE_MAP\\n\\tvec4 mapTexel = texture2D( map, uv );\\n\\tdiffuseColor *= mapTexelToLinear( mapTexel );\\n#endif\\n#ifdef USE_ALPHAMAP\\n\\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\\n#endif\";\n\n\tvar map_particle_pars_fragment = \"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\\n\\tuniform mat3 uvTransform;\\n#endif\\n#ifdef USE_MAP\\n\\tuniform sampler2D map;\\n#endif\\n#ifdef USE_ALPHAMAP\\n\\tuniform sampler2D alphaMap;\\n#endif\";\n\n\tvar metalnessmap_fragment = \"float metalnessFactor = metalness;\\n#ifdef USE_METALNESSMAP\\n\\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\\n\\tmetalnessFactor *= texelMetalness.b;\\n#endif\";\n\n\tvar metalnessmap_pars_fragment = \"#ifdef USE_METALNESSMAP\\n\\tuniform sampler2D metalnessMap;\\n#endif\";\n\n\tvar morphnormal_vertex = \"#ifdef USE_MORPHNORMALS\\n\\tobjectNormal *= morphTargetBaseInfluence;\\n\\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\\n\\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\\n\\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\\n\\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\\n#endif\";\n\n\tvar morphtarget_pars_vertex = \"#ifdef USE_MORPHTARGETS\\n\\tuniform float morphTargetBaseInfluence;\\n\\t#ifndef USE_MORPHNORMALS\\n\\tuniform float morphTargetInfluences[ 8 ];\\n\\t#else\\n\\tuniform float morphTargetInfluences[ 4 ];\\n\\t#endif\\n#endif\";\n\n\tvar morphtarget_vertex = \"#ifdef USE_MORPHTARGETS\\n\\ttransformed *= morphTargetBaseInfluence;\\n\\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\\n\\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\\n\\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\\n\\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\\n\\t#ifndef USE_MORPHNORMALS\\n\\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\\n\\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\\n\\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\\n\\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\\n\\t#endif\\n#endif\";\n\n\tvar normal_fragment_begin = \"#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\\t#ifdef USE_TANGENT\\n\\t\\tvec3 tangent = normalize( vTangent );\\n\\t\\tvec3 bitangent = normalize( vBitangent );\\n\\t\\t#ifdef DOUBLE_SIDED\\n\\t\\t\\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\t\\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\t#endif\\n\\t\\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\\n\\t\\t\\tmat3 vTBN = mat3( tangent, bitangent, normal );\\n\\t\\t#endif\\n\\t#endif\\n#endif\\nvec3 geometryNormal = normal;\";\n\n\tvar normal_fragment_maps = \"#ifdef OBJECTSPACE_NORMALMAP\\n\\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\\n\\t#ifdef FLIP_SIDED\\n\\t\\tnormal = - normal;\\n\\t#endif\\n\\t#ifdef DOUBLE_SIDED\\n\\t\\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t#endif\\n\\tnormal = normalize( normalMatrix * normal );\\n#elif defined( TANGENTSPACE_NORMALMAP )\\n\\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\\n\\tmapN.xy *= normalScale;\\n\\t#ifdef USE_TANGENT\\n\\t\\tnormal = normalize( vTBN * mapN );\\n\\t#else\\n\\t\\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\\n\\t#endif\\n#elif defined( USE_BUMPMAP )\\n\\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\\n#endif\";\n\n\tvar normalmap_pars_fragment = \"#ifdef USE_NORMALMAP\\n\\tuniform sampler2D normalMap;\\n\\tuniform vec2 normalScale;\\n#endif\\n#ifdef OBJECTSPACE_NORMALMAP\\n\\tuniform mat3 normalMatrix;\\n#endif\\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\\n\\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\\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\\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\\n\\t\\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\\n\\t\\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\\n\\t\\tvec3 N = normalize( surf_norm );\\n\\t\\tmat3 tsn = mat3( S, T, N );\\n\\t\\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\\n\\t\\treturn normalize( tsn * mapN );\\n\\t}\\n#endif\";\n\n\tvar clearcoat_normal_fragment_begin = \"#ifdef CLEARCOAT\\n\\tvec3 clearcoatNormal = geometryNormal;\\n#endif\";\n\n\tvar clearcoat_normal_fragment_maps = \"#ifdef USE_CLEARCOAT_NORMALMAP\\n\\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\\n\\tclearcoatMapN.xy *= clearcoatNormalScale;\\n\\t#ifdef USE_TANGENT\\n\\t\\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\\n\\t#else\\n\\t\\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\\n\\t#endif\\n#endif\";\n\n\tvar clearcoat_normalmap_pars_fragment = \"#ifdef USE_CLEARCOAT_NORMALMAP\\n\\tuniform sampler2D clearcoatNormalMap;\\n\\tuniform vec2 clearcoatNormalScale;\\n#endif\";\n\n\tvar 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}\\nvec4 pack2HalfToRGBA( vec2 v ) {\\n\\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\\n\\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\\n}\\nvec2 unpack2HalfToRGBA( vec4 v ) {\\n\\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\\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\n\tvar premultiplied_alpha_fragment = \"#ifdef PREMULTIPLIED_ALPHA\\n\\tgl_FragColor.rgb *= gl_FragColor.a;\\n#endif\";\n\n\tvar project_vertex = \"vec4 mvPosition = vec4( transformed, 1.0 );\\n#ifdef USE_INSTANCING\\n\\tmvPosition = instanceMatrix * mvPosition;\\n#endif\\nmvPosition = modelViewMatrix * mvPosition;\\ngl_Position = projectionMatrix * mvPosition;\";\n\n\tvar dithering_fragment = \"#ifdef DITHERING\\n\\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\\n#endif\";\n\n\tvar dithering_pars_fragment = \"#ifdef 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\n\tvar roughnessmap_fragment = \"float roughnessFactor = roughness;\\n#ifdef USE_ROUGHNESSMAP\\n\\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\\n\\troughnessFactor *= texelRoughness.g;\\n#endif\";\n\n\tvar roughnessmap_pars_fragment = \"#ifdef USE_ROUGHNESSMAP\\n\\tuniform sampler2D roughnessMap;\\n#endif\";\n\n\tvar shadowmap_pars_fragment = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t\\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\\n\\t\\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\\n\\t}\\n\\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\\n\\t\\treturn unpack2HalfToRGBA( texture2D( shadow, uv ) );\\n\\t}\\n\\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\\n\\t\\tfloat occlusion = 1.0;\\n\\t\\tvec2 distribution = texture2DDistribution( shadow, uv );\\n\\t\\tfloat hard_shadow = step( compare , distribution.x );\\n\\t\\tif (hard_shadow != 1.0 ) {\\n\\t\\t\\tfloat distance = compare - distribution.x ;\\n\\t\\t\\tfloat variance = max( 0.00000, distribution.y * distribution.y );\\n\\t\\t\\tfloat softness_probability = variance / (variance + distance * distance );\\t\\t\\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\\t\\t\\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\\n\\t\\t}\\n\\t\\treturn occlusion;\\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 ) + 0.5 ) * texelSize;\\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\\tfloat dx2 = dx0 / 2.0;\\n\\t\\t\\tfloat dy2 = dy0 / 2.0;\\n\\t\\t\\tfloat dx3 = dx1 / 2.0;\\n\\t\\t\\tfloat dy3 = dy1 / 2.0;\\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( dx2, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), 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( dx2, dy3 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\\n\\t\\t\\t\\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), 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 / 17.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#elif defined( SHADOWMAP_TYPE_VSM )\\n\\t\\t\\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\\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 ) || defined( SHADOWMAP_TYPE_VSM )\\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\n\tvar shadowmap_pars_vertex = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t\\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t\\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\\n\\t#endif\\n#endif\";\n\n\tvar shadowmap_vertex = \"#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\\n\\t}\\n\\t#endif\\n#endif\";\n\n\tvar shadowmask_pars_fragment = \"float getShadowMask() {\\n\\tfloat shadow = 1.0;\\n\\t#ifdef USE_SHADOWMAP\\n\\t#if NUM_DIR_LIGHT_SHADOWS > 0\\n\\tDirectionalLight directionalLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tdirectionalLight = directionalLights[ i ];\\n\\t\\tshadow *= all( bvec2( directionalLight.shadow, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\\n\\t}\\n\\t#endif\\n\\t#if NUM_SPOT_LIGHT_SHADOWS > 0\\n\\tSpotLight spotLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tspotLight = spotLights[ i ];\\n\\t\\tshadow *= all( bvec2( spotLight.shadow, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\\n\\t}\\n\\t#endif\\n\\t#if NUM_POINT_LIGHT_SHADOWS > 0\\n\\tPointLight pointLight;\\n\\t#pragma unroll_loop\\n\\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\\n\\t\\tpointLight = pointLights[ i ];\\n\\t\\tshadow *= all( bvec2( pointLight.shadow, receiveShadow ) ) ? 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\n\tvar 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\";\n\n\tvar skinning_pars_vertex = \"#ifdef USE_SKINNING\\n\\tuniform mat4 bindMatrix;\\n\\tuniform mat4 bindMatrixInverse;\\n\\t#ifdef BONE_TEXTURE\\n\\t\\tuniform highp 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\n\tvar 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\n\tvar 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\\t#ifdef USE_TANGENT\\n\\t\\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\\n\\t#endif\\n#endif\";\n\n\tvar 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\";\n\n\tvar specularmap_pars_fragment = \"#ifdef USE_SPECULARMAP\\n\\tuniform sampler2D specularMap;\\n#endif\";\n\n\tvar tonemapping_fragment = \"#if defined( TONE_MAPPING )\\n\\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\\n#endif\";\n\n\tvar tonemapping_pars_fragment = \"#ifndef saturate\\n#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}\\nvec3 ACESFilmicToneMapping( vec3 color ) {\\n\\tcolor *= toneMappingExposure;\\n\\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\\n}\";\n\n\tvar uv_pars_fragment = \"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\\n\\tvarying vec2 vUv;\\n#endif\";\n\n\tvar uv_pars_vertex = \"#ifdef USE_UV\\n\\t#ifdef UVS_VERTEX_ONLY\\n\\t\\tvec2 vUv;\\n\\t#else\\n\\t\\tvarying vec2 vUv;\\n\\t#endif\\n\\tuniform mat3 uvTransform;\\n#endif\";\n\n\tvar uv_vertex = \"#ifdef USE_UV\\n\\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\\n#endif\";\n\n\tvar uv2_pars_fragment = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tvarying vec2 vUv2;\\n#endif\";\n\n\tvar uv2_pars_vertex = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tattribute vec2 uv2;\\n\\tvarying vec2 vUv2;\\n\\tuniform mat3 uv2Transform;\\n#endif\";\n\n\tvar uv2_vertex = \"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\\n\\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\\n#endif\";\n\n\tvar worldpos_vertex = \"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\\n\\tvec4 worldPosition = vec4( transformed, 1.0 );\\n\\t#ifdef USE_INSTANCING\\n\\t\\tworldPosition = instanceMatrix * worldPosition;\\n\\t#endif\\n\\tworldPosition = modelMatrix * worldPosition;\\n#endif\";\n\n\tvar background_frag = \"uniform sampler2D t2D;\\nvarying vec2 vUv;\\nvoid main() {\\n\\tvec4 texColor = texture2D( t2D, vUv );\\n\\tgl_FragColor = mapTexelToLinear( texColor );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar background_vert = \"varying vec2 vUv;\\nuniform mat3 uvTransform;\\nvoid main() {\\n\\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\\n\\tgl_Position = vec4( position.xy, 1.0, 1.0 );\\n}\";\n\n\tvar cube_frag = \"#include \\nuniform float opacity;\\nvarying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvec3 vReflect = vWorldDirection;\\n\\t#include \\n\\tgl_FragColor = envColor;\\n\\tgl_FragColor.a *= opacity;\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar cube_vert = \"varying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvWorldDirection = transformDirection( position, modelMatrix );\\n\\t#include \\n\\t#include \\n\\tgl_Position.z = gl_Position.w;\\n}\";\n\n\tvar depth_frag = \"#if DEPTH_PACKING == 3200\\n\\tuniform float opacity;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( 1.0 );\\n\\t#if DEPTH_PACKING == 3200\\n\\t\\tdiffuseColor.a = opacity;\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#if DEPTH_PACKING == 3200\\n\\t\\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\\n\\t#elif DEPTH_PACKING == 3201\\n\\t\\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\\n\\t#endif\\n}\";\n\n\tvar depth_vert = \"#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#ifdef USE_DISPLACEMENTMAP\\n\\t\\t#include \\n\\t\\t#include \\n\\t\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar distanceRGBA_frag = \"#define DISTANCE\\nuniform vec3 referencePosition;\\nuniform float nearDistance;\\nuniform float farDistance;\\nvarying vec3 vWorldPosition;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main () {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( 1.0 );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\tfloat dist = length( vWorldPosition - referencePosition );\\n\\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\\n\\tdist = saturate( dist );\\n\\tgl_FragColor = packDepthToRGBA( dist );\\n}\";\n\n\tvar distanceRGBA_vert = \"#define DISTANCE\\nvarying vec3 vWorldPosition;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#ifdef USE_DISPLACEMENTMAP\\n\\t\\t#include \\n\\t\\t#include \\n\\t\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvWorldPosition = worldPosition.xyz;\\n}\";\n\n\tvar equirect_frag = \"uniform sampler2D tEquirect;\\nvarying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvec3 direction = normalize( vWorldDirection );\\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\\tvec4 texColor = texture2D( tEquirect, sampleUV );\\n\\tgl_FragColor = mapTexelToLinear( texColor );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar equirect_vert = \"varying vec3 vWorldDirection;\\n#include \\nvoid main() {\\n\\tvWorldDirection = transformDirection( position, modelMatrix );\\n\\t#include \\n\\t#include \\n}\";\n\n\tvar linedashed_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\nuniform float dashSize;\\nuniform float totalSize;\\nvarying float vLineDistance;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar linedashed_vert = \"uniform float scale;\\nattribute float lineDistance;\\nvarying float vLineDistance;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvLineDistance = scale * lineDistance;\\n\\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\\n\\tgl_Position = projectionMatrix * mvPosition;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshbasic_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\\n\\t#ifdef USE_LIGHTMAP\\n\\t\\n\\t\\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\\n\\t\\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\\n\\t#else\\n\\t\\treflectedLight.indirectDiffuse += vec3( 1.0 );\\n\\t#endif\\n\\t#include \\n\\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\\n\\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshbasic_vert = \"#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#ifdef USE_ENVMAP\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshlambert_frag = \"uniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform float opacity;\\nvarying vec3 vLightFront;\\nvarying vec3 vIndirectFront;\\n#ifdef DOUBLE_SIDED\\n\\tvarying vec3 vLightBack;\\n\\tvarying vec3 vIndirectBack;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\\n\\t#ifdef DOUBLE_SIDED\\n\\t\\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\\n\\t#else\\n\\t\\treflectedLight.indirectDiffuse += vIndirectFront;\\n\\t#endif\\n\\t#include \\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 \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshlambert_vert = \"#define LAMBERT\\nvarying vec3 vLightFront;\\nvarying vec3 vIndirectFront;\\n#ifdef DOUBLE_SIDED\\n\\tvarying vec3 vLightBack;\\n\\tvarying vec3 vIndirectBack;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshmatcap_frag = \"#define MATCAP\\nuniform vec3 diffuse;\\nuniform float opacity;\\nuniform sampler2D matcap;\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 viewDir = normalize( vViewPosition );\\n\\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\\n\\tvec3 y = cross( viewDir, x );\\n\\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\\n\\t#ifdef USE_MATCAP\\n\\t\\tvec4 matcapColor = texture2D( matcap, uv );\\n\\t\\tmatcapColor = matcapTexelToLinear( matcapColor );\\n\\t#else\\n\\t\\tvec4 matcapColor = vec4( 1.0 );\\n\\t#endif\\n\\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshmatcap_vert = \"#define MATCAP\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#ifndef FLAT_SHADED\\n\\t\\tvNormal = normalize( transformedNormal );\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n}\";\n\n\tvar meshtoon_frag = \"#define TOON\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform vec3 specular;\\nuniform float shininess;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshtoon_vert = \"#define TOON\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphong_frag = \"#define PHONG\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform vec3 specular;\\nuniform float shininess;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\t#include \\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphong_vert = \"#define PHONG\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphysical_frag = \"#define STANDARD\\n#ifdef PHYSICAL\\n\\t#define REFLECTIVITY\\n\\t#define CLEARCOAT\\n\\t#define TRANSPARENCY\\n#endif\\nuniform vec3 diffuse;\\nuniform vec3 emissive;\\nuniform float roughness;\\nuniform float metalness;\\nuniform float opacity;\\n#ifdef TRANSPARENCY\\n\\tuniform float transparency;\\n#endif\\n#ifdef REFLECTIVITY\\n\\tuniform float reflectivity;\\n#endif\\n#ifdef CLEARCOAT\\n\\tuniform float clearcoat;\\n\\tuniform float clearcoatRoughness;\\n#endif\\n#ifdef USE_SHEEN\\n\\tuniform vec3 sheen;\\n#endif\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\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 \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\\n\\t#ifdef TRANSPARENCY\\n\\t\\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\\n\\t#endif\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar meshphysical_vert = \"#define STANDARD\\nvarying vec3 vViewPosition;\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n\\t#ifdef USE_TANGENT\\n\\t\\tvTangent = normalize( transformedTangent );\\n\\t\\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\\n\\t#endif\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tvViewPosition = - mvPosition.xyz;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar normal_frag = \"#define NORMAL\\nuniform float opacity;\\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\\n}\";\n\n\tvar normal_vert = \"#define NORMAL\\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvarying vec3 vViewPosition;\\n#endif\\n#ifndef FLAT_SHADED\\n\\tvarying vec3 vNormal;\\n\\t#ifdef USE_TANGENT\\n\\t\\tvarying vec3 vTangent;\\n\\t\\tvarying vec3 vBitangent;\\n\\t#endif\\n#endif\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#ifndef FLAT_SHADED\\n\\tvNormal = normalize( transformedNormal );\\n\\t#ifdef USE_TANGENT\\n\\t\\tvTangent = normalize( transformedTangent );\\n\\t\\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\\n\\t#endif\\n#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\\n\\tvViewPosition = - mvPosition.xyz;\\n#endif\\n}\";\n\n\tvar points_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec3 outgoingLight = vec3( 0.0 );\\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar points_vert = \"uniform float size;\\nuniform float scale;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\tgl_PointSize = size;\\n\\t#ifdef USE_SIZEATTENUATION\\n\\t\\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\\n\\t\\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\\n\\t#endif\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar shadow_frag = \"uniform vec3 color;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\\n\\t#include \\n}\";\n\n\tvar shadow_vert = \"#include \\n#include \\nvoid main() {\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar sprite_frag = \"uniform vec3 diffuse;\\nuniform float opacity;\\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec3 outgoingLight = vec3( 0.0 );\\n\\tvec4 diffuseColor = vec4( diffuse, opacity );\\n\\t#include \\n\\t#include \\n\\t#include \\n\\t#include \\n\\toutgoingLight = diffuseColor.rgb;\\n\\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar sprite_vert = \"uniform float rotation;\\nuniform vec2 center;\\n#include \\n#include \\n#include \\n#include \\n#include \\nvoid main() {\\n\\t#include \\n\\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\\n\\tvec2 scale;\\n\\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\\n\\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\\n\\t#ifndef USE_SIZEATTENUATION\\n\\t\\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\\n\\t\\tif ( isPerspective ) scale *= - mvPosition.z;\\n\\t#endif\\n\\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\\n\\tvec2 rotatedPosition;\\n\\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\\n\\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\\n\\tmvPosition.xy += rotatedPosition;\\n\\tgl_Position = projectionMatrix * mvPosition;\\n\\t#include \\n\\t#include \\n\\t#include \\n}\";\n\n\tvar ShaderChunk = {\r\n\t\talphamap_fragment: alphamap_fragment,\r\n\t\talphamap_pars_fragment: alphamap_pars_fragment,\r\n\t\talphatest_fragment: alphatest_fragment,\r\n\t\taomap_fragment: aomap_fragment,\r\n\t\taomap_pars_fragment: aomap_pars_fragment,\r\n\t\tbegin_vertex: begin_vertex,\r\n\t\tbeginnormal_vertex: beginnormal_vertex,\r\n\t\tbsdfs: bsdfs,\r\n\t\tbumpmap_pars_fragment: bumpmap_pars_fragment,\r\n\t\tclipping_planes_fragment: clipping_planes_fragment,\r\n\t\tclipping_planes_pars_fragment: clipping_planes_pars_fragment,\r\n\t\tclipping_planes_pars_vertex: clipping_planes_pars_vertex,\r\n\t\tclipping_planes_vertex: clipping_planes_vertex,\r\n\t\tcolor_fragment: color_fragment,\r\n\t\tcolor_pars_fragment: color_pars_fragment,\r\n\t\tcolor_pars_vertex: color_pars_vertex,\r\n\t\tcolor_vertex: color_vertex,\r\n\t\tcommon: common,\r\n\t\tcube_uv_reflection_fragment: cube_uv_reflection_fragment,\r\n\t\tdefaultnormal_vertex: defaultnormal_vertex,\r\n\t\tdisplacementmap_pars_vertex: displacementmap_pars_vertex,\r\n\t\tdisplacementmap_vertex: displacementmap_vertex,\r\n\t\temissivemap_fragment: emissivemap_fragment,\r\n\t\temissivemap_pars_fragment: emissivemap_pars_fragment,\r\n\t\tencodings_fragment: encodings_fragment,\r\n\t\tencodings_pars_fragment: encodings_pars_fragment,\r\n\t\tenvmap_fragment: envmap_fragment,\r\n\t\tenvmap_common_pars_fragment: envmap_common_pars_fragment,\r\n\t\tenvmap_pars_fragment: envmap_pars_fragment,\r\n\t\tenvmap_pars_vertex: envmap_pars_vertex,\r\n\t\tenvmap_physical_pars_fragment: envmap_physical_pars_fragment,\r\n\t\tenvmap_vertex: envmap_vertex,\r\n\t\tfog_vertex: fog_vertex,\r\n\t\tfog_pars_vertex: fog_pars_vertex,\r\n\t\tfog_fragment: fog_fragment,\r\n\t\tfog_pars_fragment: fog_pars_fragment,\r\n\t\tgradientmap_pars_fragment: gradientmap_pars_fragment,\r\n\t\tlightmap_fragment: lightmap_fragment,\r\n\t\tlightmap_pars_fragment: lightmap_pars_fragment,\r\n\t\tlights_lambert_vertex: lights_lambert_vertex,\r\n\t\tlights_pars_begin: lights_pars_begin,\r\n\t\tlights_toon_fragment: lights_toon_fragment,\r\n\t\tlights_toon_pars_fragment: lights_toon_pars_fragment,\r\n\t\tlights_phong_fragment: lights_phong_fragment,\r\n\t\tlights_phong_pars_fragment: lights_phong_pars_fragment,\r\n\t\tlights_physical_fragment: lights_physical_fragment,\r\n\t\tlights_physical_pars_fragment: lights_physical_pars_fragment,\r\n\t\tlights_fragment_begin: lights_fragment_begin,\r\n\t\tlights_fragment_maps: lights_fragment_maps,\r\n\t\tlights_fragment_end: lights_fragment_end,\r\n\t\tlogdepthbuf_fragment: logdepthbuf_fragment,\r\n\t\tlogdepthbuf_pars_fragment: logdepthbuf_pars_fragment,\r\n\t\tlogdepthbuf_pars_vertex: logdepthbuf_pars_vertex,\r\n\t\tlogdepthbuf_vertex: logdepthbuf_vertex,\r\n\t\tmap_fragment: map_fragment,\r\n\t\tmap_pars_fragment: map_pars_fragment,\r\n\t\tmap_particle_fragment: map_particle_fragment,\r\n\t\tmap_particle_pars_fragment: map_particle_pars_fragment,\r\n\t\tmetalnessmap_fragment: metalnessmap_fragment,\r\n\t\tmetalnessmap_pars_fragment: metalnessmap_pars_fragment,\r\n\t\tmorphnormal_vertex: morphnormal_vertex,\r\n\t\tmorphtarget_pars_vertex: morphtarget_pars_vertex,\r\n\t\tmorphtarget_vertex: morphtarget_vertex,\r\n\t\tnormal_fragment_begin: normal_fragment_begin,\r\n\t\tnormal_fragment_maps: normal_fragment_maps,\r\n\t\tnormalmap_pars_fragment: normalmap_pars_fragment,\r\n\t\tclearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,\r\n\t\tclearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,\r\n\t\tclearcoat_normalmap_pars_fragment: clearcoat_normalmap_pars_fragment,\r\n\t\tpacking: packing,\r\n\t\tpremultiplied_alpha_fragment: premultiplied_alpha_fragment,\r\n\t\tproject_vertex: project_vertex,\r\n\t\tdithering_fragment: dithering_fragment,\r\n\t\tdithering_pars_fragment: dithering_pars_fragment,\r\n\t\troughnessmap_fragment: roughnessmap_fragment,\r\n\t\troughnessmap_pars_fragment: roughnessmap_pars_fragment,\r\n\t\tshadowmap_pars_fragment: shadowmap_pars_fragment,\r\n\t\tshadowmap_pars_vertex: shadowmap_pars_vertex,\r\n\t\tshadowmap_vertex: shadowmap_vertex,\r\n\t\tshadowmask_pars_fragment: shadowmask_pars_fragment,\r\n\t\tskinbase_vertex: skinbase_vertex,\r\n\t\tskinning_pars_vertex: skinning_pars_vertex,\r\n\t\tskinning_vertex: skinning_vertex,\r\n\t\tskinnormal_vertex: skinnormal_vertex,\r\n\t\tspecularmap_fragment: specularmap_fragment,\r\n\t\tspecularmap_pars_fragment: specularmap_pars_fragment,\r\n\t\ttonemapping_fragment: tonemapping_fragment,\r\n\t\ttonemapping_pars_fragment: tonemapping_pars_fragment,\r\n\t\tuv_pars_fragment: uv_pars_fragment,\r\n\t\tuv_pars_vertex: uv_pars_vertex,\r\n\t\tuv_vertex: uv_vertex,\r\n\t\tuv2_pars_fragment: uv2_pars_fragment,\r\n\t\tuv2_pars_vertex: uv2_pars_vertex,\r\n\t\tuv2_vertex: uv2_vertex,\r\n\t\tworldpos_vertex: worldpos_vertex,\r\n\r\n\t\tbackground_frag: background_frag,\r\n\t\tbackground_vert: background_vert,\r\n\t\tcube_frag: cube_frag,\r\n\t\tcube_vert: cube_vert,\r\n\t\tdepth_frag: depth_frag,\r\n\t\tdepth_vert: depth_vert,\r\n\t\tdistanceRGBA_frag: distanceRGBA_frag,\r\n\t\tdistanceRGBA_vert: distanceRGBA_vert,\r\n\t\tequirect_frag: equirect_frag,\r\n\t\tequirect_vert: equirect_vert,\r\n\t\tlinedashed_frag: linedashed_frag,\r\n\t\tlinedashed_vert: linedashed_vert,\r\n\t\tmeshbasic_frag: meshbasic_frag,\r\n\t\tmeshbasic_vert: meshbasic_vert,\r\n\t\tmeshlambert_frag: meshlambert_frag,\r\n\t\tmeshlambert_vert: meshlambert_vert,\r\n\t\tmeshmatcap_frag: meshmatcap_frag,\r\n\t\tmeshmatcap_vert: meshmatcap_vert,\r\n\t\tmeshtoon_frag: meshtoon_frag,\r\n\t\tmeshtoon_vert: meshtoon_vert,\r\n\t\tmeshphong_frag: meshphong_frag,\r\n\t\tmeshphong_vert: meshphong_vert,\r\n\t\tmeshphysical_frag: meshphysical_frag,\r\n\t\tmeshphysical_vert: meshphysical_vert,\r\n\t\tnormal_frag: normal_frag,\r\n\t\tnormal_vert: normal_vert,\r\n\t\tpoints_frag: points_frag,\r\n\t\tpoints_vert: points_vert,\r\n\t\tshadow_frag: shadow_frag,\r\n\t\tshadow_vert: shadow_vert,\r\n\t\tsprite_frag: sprite_frag,\r\n\t\tsprite_vert: sprite_vert\r\n\t};\n\n\t/**\r\n\t * Uniforms library for shared webgl shaders\r\n\t */\r\n\r\n\tvar UniformsLib = {\r\n\r\n\t\tcommon: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\r\n\t\t\tmap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() },\r\n\t\t\tuv2Transform: { value: new Matrix3() },\r\n\r\n\t\t\talphaMap: { value: null },\r\n\r\n\t\t},\r\n\r\n\t\tspecularmap: {\r\n\r\n\t\t\tspecularMap: { value: null },\r\n\r\n\t\t},\r\n\r\n\t\tenvmap: {\r\n\r\n\t\t\tenvMap: { value: null },\r\n\t\t\tflipEnvMap: { value: - 1 },\r\n\t\t\treflectivity: { value: 1.0 },\r\n\t\t\trefractionRatio: { value: 0.98 },\r\n\t\t\tmaxMipLevel: { value: 0 }\r\n\r\n\t\t},\r\n\r\n\t\taomap: {\r\n\r\n\t\t\taoMap: { value: null },\r\n\t\t\taoMapIntensity: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\tlightmap: {\r\n\r\n\t\t\tlightMap: { value: null },\r\n\t\t\tlightMapIntensity: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\temissivemap: {\r\n\r\n\t\t\temissiveMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tbumpmap: {\r\n\r\n\t\t\tbumpMap: { value: null },\r\n\t\t\tbumpScale: { value: 1 }\r\n\r\n\t\t},\r\n\r\n\t\tnormalmap: {\r\n\r\n\t\t\tnormalMap: { value: null },\r\n\t\t\tnormalScale: { value: new Vector2( 1, 1 ) }\r\n\r\n\t\t},\r\n\r\n\t\tdisplacementmap: {\r\n\r\n\t\t\tdisplacementMap: { value: null },\r\n\t\t\tdisplacementScale: { value: 1 },\r\n\t\t\tdisplacementBias: { value: 0 }\r\n\r\n\t\t},\r\n\r\n\t\troughnessmap: {\r\n\r\n\t\t\troughnessMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tmetalnessmap: {\r\n\r\n\t\t\tmetalnessMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tgradientmap: {\r\n\r\n\t\t\tgradientMap: { value: null }\r\n\r\n\t\t},\r\n\r\n\t\tfog: {\r\n\r\n\t\t\tfogDensity: { value: 0.00025 },\r\n\t\t\tfogNear: { value: 1 },\r\n\t\t\tfogFar: { value: 2000 },\r\n\t\t\tfogColor: { value: new Color( 0xffffff ) }\r\n\r\n\t\t},\r\n\r\n\t\tlights: {\r\n\r\n\t\t\tambientLightColor: { value: [] },\r\n\r\n\t\t\tlightProbe: { value: [] },\r\n\r\n\t\t\tdirectionalLights: { value: [], properties: {\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tcolor: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {}\r\n\t\t\t} },\r\n\r\n\t\t\tdirectionalShadowMap: { value: [] },\r\n\t\t\tdirectionalShadowMatrix: { value: [] },\r\n\r\n\t\t\tspotLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tdistance: {},\r\n\t\t\t\tconeCos: {},\r\n\t\t\t\tpenumbraCos: {},\r\n\t\t\t\tdecay: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {}\r\n\t\t\t} },\r\n\r\n\t\t\tspotShadowMap: { value: [] },\r\n\t\t\tspotShadowMatrix: { value: [] },\r\n\r\n\t\t\tpointLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\tdecay: {},\r\n\t\t\t\tdistance: {},\r\n\r\n\t\t\t\tshadow: {},\r\n\t\t\t\tshadowBias: {},\r\n\t\t\t\tshadowRadius: {},\r\n\t\t\t\tshadowMapSize: {},\r\n\t\t\t\tshadowCameraNear: {},\r\n\t\t\t\tshadowCameraFar: {}\r\n\t\t\t} },\r\n\r\n\t\t\tpointShadowMap: { value: [] },\r\n\t\t\tpointShadowMatrix: { value: [] },\r\n\r\n\t\t\themisphereLights: { value: [], properties: {\r\n\t\t\t\tdirection: {},\r\n\t\t\t\tskyColor: {},\r\n\t\t\t\tgroundColor: {}\r\n\t\t\t} },\r\n\r\n\t\t\t// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src\r\n\t\t\trectAreaLights: { value: [], properties: {\r\n\t\t\t\tcolor: {},\r\n\t\t\t\tposition: {},\r\n\t\t\t\twidth: {},\r\n\t\t\t\theight: {}\r\n\t\t\t} }\r\n\r\n\t\t},\r\n\r\n\t\tpoints: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\t\t\tsize: { value: 1.0 },\r\n\t\t\tscale: { value: 1.0 },\r\n\t\t\tmap: { value: null },\r\n\t\t\talphaMap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() }\r\n\r\n\t\t},\r\n\r\n\t\tsprite: {\r\n\r\n\t\t\tdiffuse: { value: new Color( 0xeeeeee ) },\r\n\t\t\topacity: { value: 1.0 },\r\n\t\t\tcenter: { value: new Vector2( 0.5, 0.5 ) },\r\n\t\t\trotation: { value: 0.0 },\r\n\t\t\tmap: { value: null },\r\n\t\t\talphaMap: { value: null },\r\n\t\t\tuvTransform: { value: new Matrix3() }\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t */\r\n\r\n\tvar ShaderLib = {\r\n\r\n\t\tbasic: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshbasic_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshbasic_frag\r\n\r\n\t\t},\r\n\r\n\t\tlambert: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshlambert_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshlambert_frag\r\n\r\n\t\t},\r\n\r\n\t\tphong: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\tspecular: { value: new Color( 0x111111 ) },\r\n\t\t\t\t\tshininess: { value: 30 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshphong_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshphong_frag\r\n\r\n\t\t},\r\n\r\n\t\tstandard: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.roughnessmap,\r\n\t\t\t\tUniformsLib.metalnessmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\troughness: { value: 0.5 },\r\n\t\t\t\t\tmetalness: { value: 0.5 },\r\n\t\t\t\t\tenvMapIntensity: { value: 1 } // temporary\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshphysical_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshphysical_frag\r\n\r\n\t\t},\r\n\r\n\t\ttoon: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.specularmap,\r\n\t\t\t\tUniformsLib.aomap,\r\n\t\t\t\tUniformsLib.lightmap,\r\n\t\t\t\tUniformsLib.emissivemap,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.gradientmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\t{\r\n\t\t\t\t\temissive: { value: new Color( 0x000000 ) },\r\n\t\t\t\t\tspecular: { value: new Color( 0x111111 ) },\r\n\t\t\t\t\tshininess: { value: 30 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshtoon_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshtoon_frag\r\n\r\n\t\t},\r\n\r\n\t\tmatcap: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tmatcap: { value: null }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.meshmatcap_vert,\r\n\t\t\tfragmentShader: ShaderChunk.meshmatcap_frag\r\n\r\n\t\t},\r\n\r\n\t\tpoints: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.points,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.points_vert,\r\n\t\t\tfragmentShader: ShaderChunk.points_frag\r\n\r\n\t\t},\r\n\r\n\t\tdashed: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tscale: { value: 1 },\r\n\t\t\t\t\tdashSize: { value: 1 },\r\n\t\t\t\t\ttotalSize: { value: 2 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.linedashed_vert,\r\n\t\t\tfragmentShader: ShaderChunk.linedashed_frag\r\n\r\n\t\t},\r\n\r\n\t\tdepth: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.displacementmap\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.depth_vert,\r\n\t\t\tfragmentShader: ShaderChunk.depth_frag\r\n\r\n\t\t},\r\n\r\n\t\tnormal: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.bumpmap,\r\n\t\t\t\tUniformsLib.normalmap,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\t{\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.normal_vert,\r\n\t\t\tfragmentShader: ShaderChunk.normal_frag\r\n\r\n\t\t},\r\n\r\n\t\tsprite: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.sprite,\r\n\t\t\t\tUniformsLib.fog\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.sprite_vert,\r\n\t\t\tfragmentShader: ShaderChunk.sprite_frag\r\n\r\n\t\t},\r\n\r\n\t\tbackground: {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\tuvTransform: { value: new Matrix3() },\r\n\t\t\t\tt2D: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: ShaderChunk.background_vert,\r\n\t\t\tfragmentShader: ShaderChunk.background_frag\r\n\r\n\t\t},\r\n\t\t/* -------------------------------------------------------------------------\r\n\t\t//\tCube map shader\r\n\t\t ------------------------------------------------------------------------- */\r\n\r\n\t\tcube: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.envmap,\r\n\t\t\t\t{\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.cube_vert,\r\n\t\t\tfragmentShader: ShaderChunk.cube_frag\r\n\r\n\t\t},\r\n\r\n\t\tequirect: {\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\ttEquirect: { value: null },\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: ShaderChunk.equirect_vert,\r\n\t\t\tfragmentShader: ShaderChunk.equirect_frag\r\n\r\n\t\t},\r\n\r\n\t\tdistanceRGBA: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.common,\r\n\t\t\t\tUniformsLib.displacementmap,\r\n\t\t\t\t{\r\n\t\t\t\t\treferencePosition: { value: new Vector3() },\r\n\t\t\t\t\tnearDistance: { value: 1 },\r\n\t\t\t\t\tfarDistance: { value: 1000 }\r\n\t\t\t\t}\r\n\t\t\t] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.distanceRGBA_vert,\r\n\t\t\tfragmentShader: ShaderChunk.distanceRGBA_frag\r\n\r\n\t\t},\r\n\r\n\t\tshadow: {\r\n\r\n\t\t\tuniforms: mergeUniforms( [\r\n\t\t\t\tUniformsLib.lights,\r\n\t\t\t\tUniformsLib.fog,\r\n\t\t\t\t{\r\n\t\t\t\t\tcolor: { value: new Color( 0x00000 ) },\r\n\t\t\t\t\topacity: { value: 1.0 }\r\n\t\t\t\t} ] ),\r\n\r\n\t\t\tvertexShader: ShaderChunk.shadow_vert,\r\n\t\t\tfragmentShader: ShaderChunk.shadow_frag\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tShaderLib.physical = {\r\n\r\n\t\tuniforms: mergeUniforms( [\r\n\t\t\tShaderLib.standard.uniforms,\r\n\t\t\t{\r\n\t\t\t\ttransparency: { value: 0 },\r\n\t\t\t\tclearcoat: { value: 0 },\r\n\t\t\t\tclearcoatRoughness: { value: 0 },\r\n\t\t\t\tsheen: { value: new Color( 0x000000 ) },\r\n\t\t\t\tclearcoatNormalScale: { value: new Vector2( 1, 1 ) },\r\n\t\t\t\tclearcoatNormalMap: { value: null },\r\n\t\t\t}\r\n\t\t] ),\r\n\r\n\t\tvertexShader: ShaderChunk.meshphysical_vert,\r\n\t\tfragmentShader: ShaderChunk.meshphysical_frag\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLAnimation() {\r\n\r\n\t\tvar context = null;\r\n\t\tvar isAnimating = false;\r\n\t\tvar animationLoop = null;\r\n\r\n\t\tfunction onAnimationFrame( time, frame ) {\r\n\r\n\t\t\tif ( isAnimating === false ) { return; }\r\n\r\n\t\t\tanimationLoop( time, frame );\r\n\r\n\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tstart: function () {\r\n\r\n\t\t\t\tif ( isAnimating === true ) { return; }\r\n\t\t\t\tif ( animationLoop === null ) { return; }\r\n\r\n\t\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\r\n\r\n\t\t\t\tisAnimating = true;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tstop: function () {\r\n\r\n\t\t\t\tisAnimating = false;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tsetAnimationLoop: function ( callback ) {\r\n\r\n\t\t\t\tanimationLoop = callback;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tsetContext: function ( value ) {\r\n\r\n\t\t\t\tcontext = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLAttributes( gl ) {\r\n\r\n\t\tvar buffers = new WeakMap();\r\n\r\n\t\tfunction createBuffer( attribute, bufferType ) {\r\n\r\n\t\t\tvar array = attribute.array;\r\n\t\t\tvar usage = attribute.usage;\r\n\r\n\t\t\tvar buffer = gl.createBuffer();\r\n\r\n\t\t\tgl.bindBuffer( bufferType, buffer );\r\n\t\t\tgl.bufferData( bufferType, array, usage );\r\n\r\n\t\t\tattribute.onUploadCallback();\r\n\r\n\t\t\tvar type = 5126;\r\n\r\n\t\t\tif ( array instanceof Float32Array ) {\r\n\r\n\t\t\t\ttype = 5126;\r\n\r\n\t\t\t} else if ( array instanceof Float64Array ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );\r\n\r\n\t\t\t} else if ( array instanceof Uint16Array ) {\r\n\r\n\t\t\t\ttype = 5123;\r\n\r\n\t\t\t} else if ( array instanceof Int16Array ) {\r\n\r\n\t\t\t\ttype = 5122;\r\n\r\n\t\t\t} else if ( array instanceof Uint32Array ) {\r\n\r\n\t\t\t\ttype = 5125;\r\n\r\n\t\t\t} else if ( array instanceof Int32Array ) {\r\n\r\n\t\t\t\ttype = 5124;\r\n\r\n\t\t\t} else if ( array instanceof Int8Array ) {\r\n\r\n\t\t\t\ttype = 5120;\r\n\r\n\t\t\t} else if ( array instanceof Uint8Array ) {\r\n\r\n\t\t\t\ttype = 5121;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\tbuffer: buffer,\r\n\t\t\t\ttype: type,\r\n\t\t\t\tbytesPerElement: array.BYTES_PER_ELEMENT,\r\n\t\t\t\tversion: attribute.version\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateBuffer( buffer, attribute, bufferType ) {\r\n\r\n\t\t\tvar array = attribute.array;\r\n\t\t\tvar updateRange = attribute.updateRange;\r\n\r\n\t\t\tgl.bindBuffer( bufferType, buffer );\r\n\r\n\t\t\tif ( updateRange.count === - 1 ) {\r\n\r\n\t\t\t\t// Not using update ranges\r\n\r\n\t\t\t\tgl.bufferSubData( bufferType, 0, array );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\r\n\t\t\t\t\tarray.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );\r\n\r\n\t\t\t\tupdateRange.count = - 1; // reset range\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction get( attribute ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\treturn buffers.get( attribute );\r\n\r\n\t\t}\r\n\r\n\t\tfunction remove( attribute ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\tvar data = buffers.get( attribute );\r\n\r\n\t\t\tif ( data ) {\r\n\r\n\t\t\t\tgl.deleteBuffer( data.buffer );\r\n\r\n\t\t\t\tbuffers.delete( attribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( attribute, bufferType ) {\r\n\r\n\t\t\tif ( attribute.isInterleavedBufferAttribute ) { attribute = attribute.data; }\r\n\r\n\t\t\tvar data = buffers.get( attribute );\r\n\r\n\t\t\tif ( data === undefined ) {\r\n\r\n\t\t\t\tbuffers.set( attribute, createBuffer( attribute, bufferType ) );\r\n\r\n\t\t\t} else if ( data.version < attribute.version ) {\r\n\r\n\t\t\t\tupdateBuffer( data.buffer, attribute, bufferType );\r\n\r\n\t\t\t\tdata.version = attribute.version;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: get,\r\n\t\t\tremove: remove,\r\n\t\t\tupdate: update\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// PlaneGeometry\r\n\r\n\tfunction PlaneGeometry( width, height, widthSegments, heightSegments ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'PlaneGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\twidth: width,\r\n\t\t\theight: height,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tPlaneGeometry.prototype = Object.create( Geometry.prototype );\r\n\tPlaneGeometry.prototype.constructor = PlaneGeometry;\r\n\r\n\t// PlaneBufferGeometry\r\n\r\n\tfunction PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'PlaneBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\twidth: width,\r\n\t\t\theight: height,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments\r\n\t\t};\r\n\r\n\t\twidth = width || 1;\r\n\t\theight = height || 1;\r\n\r\n\t\tvar width_half = width / 2;\r\n\t\tvar height_half = height / 2;\r\n\r\n\t\tvar gridX = Math.floor( widthSegments ) || 1;\r\n\t\tvar gridY = Math.floor( heightSegments ) || 1;\r\n\r\n\t\tvar gridX1 = gridX + 1;\r\n\t\tvar gridY1 = gridY + 1;\r\n\r\n\t\tvar segment_width = width / gridX;\r\n\t\tvar segment_height = height / gridY;\r\n\r\n\t\tvar ix, iy;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( iy = 0; iy < gridY1; iy ++ ) {\r\n\r\n\t\t\tvar y = iy * segment_height - height_half;\r\n\r\n\t\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\r\n\r\n\t\t\t\tvar x = ix * segment_width - width_half;\r\n\r\n\t\t\t\tvertices.push( x, - y, 0 );\r\n\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t\tuvs.push( ix / gridX );\r\n\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( iy = 0; iy < gridY; iy ++ ) {\r\n\r\n\t\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\r\n\r\n\t\t\t\tvar a = ix + gridX1 * iy;\r\n\t\t\t\tvar b = ix + gridX1 * ( iy + 1 );\r\n\t\t\t\tvar c = ( ix + 1 ) + gridX1 * ( iy + 1 );\r\n\t\t\t\tvar d = ( ix + 1 ) + gridX1 * iy;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tPlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tPlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLBackground( renderer, state, objects, premultipliedAlpha ) {\r\n\r\n\t\tvar clearColor = new Color( 0x000000 );\r\n\t\tvar clearAlpha = 0;\r\n\r\n\t\tvar planeMesh;\r\n\t\tvar boxMesh;\r\n\t\t// Store the current background texture and its `version`\r\n\t\t// so we can recompile the material accordingly.\r\n\t\tvar currentBackground = null;\r\n\t\tvar currentBackgroundVersion = 0;\r\n\r\n\t\tfunction render( renderList, scene, camera, forceClear ) {\r\n\r\n\t\t\tvar background = scene.background;\r\n\r\n\t\t\t// Ignore background in AR\r\n\t\t\t// TODO: Reconsider this.\r\n\r\n\t\t\tvar xr = renderer.xr;\r\n\t\t\tvar session = xr.getSession && xr.getSession();\r\n\r\n\t\t\tif ( session && session.environmentBlendMode === 'additive' ) {\r\n\r\n\t\t\t\tbackground = null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( background === null ) {\r\n\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\t\t\t\tcurrentBackground = null;\r\n\t\t\t\tcurrentBackgroundVersion = 0;\r\n\r\n\t\t\t} else if ( background && background.isColor ) {\r\n\r\n\t\t\t\tsetClear( background, 1 );\r\n\t\t\t\tforceClear = true;\r\n\t\t\t\tcurrentBackground = null;\r\n\t\t\t\tcurrentBackgroundVersion = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderer.autoClear || forceClear ) {\r\n\r\n\t\t\t\trenderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( background && ( background.isCubeTexture || background.isWebGLRenderTargetCube || background.mapping === CubeUVReflectionMapping ) ) {\r\n\r\n\t\t\t\tif ( boxMesh === undefined ) {\r\n\r\n\t\t\t\t\tboxMesh = new Mesh(\r\n\t\t\t\t\t\tnew BoxBufferGeometry( 1, 1, 1 ),\r\n\t\t\t\t\t\tnew ShaderMaterial( {\r\n\t\t\t\t\t\t\ttype: 'BackgroundCubeMaterial',\r\n\t\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.cube.uniforms ),\r\n\t\t\t\t\t\t\tvertexShader: ShaderLib.cube.vertexShader,\r\n\t\t\t\t\t\t\tfragmentShader: ShaderLib.cube.fragmentShader,\r\n\t\t\t\t\t\t\tside: BackSide,\r\n\t\t\t\t\t\t\tdepthTest: false,\r\n\t\t\t\t\t\t\tdepthWrite: false,\r\n\t\t\t\t\t\t\tfog: false\r\n\t\t\t\t\t\t} )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tboxMesh.geometry.deleteAttribute( 'normal' );\r\n\t\t\t\t\tboxMesh.geometry.deleteAttribute( 'uv' );\r\n\r\n\t\t\t\t\tboxMesh.onBeforeRender = function ( renderer, scene, camera ) {\r\n\r\n\t\t\t\t\t\tthis.matrixWorld.copyPosition( camera.matrixWorld );\r\n\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t\t// enable code injection for non-built-in material\r\n\t\t\t\t\tObject.defineProperty( boxMesh.material, 'map', {\r\n\r\n\t\t\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\t\t\treturn this.envMap.value;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\tobjects.update( boxMesh );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar texture = background.isWebGLRenderTargetCube ? background.texture : background;\r\n\t\t\t\tboxMesh.material.envMap = texture;\r\n\r\n\t\t\t\tif ( currentBackground !== background ||\r\n\t\t\t\t currentBackgroundVersion !== texture.version ) {\r\n\r\n\t\t\t\t\tboxMesh.material.needsUpdate = true;\r\n\r\n\t\t\t\t\tcurrentBackground = background;\r\n\t\t\t\t\tcurrentBackgroundVersion = texture.version;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// push to the pre-sorted opaque render list\r\n\t\t\t\trenderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );\r\n\r\n\t\t\t} else if ( background && background.isTexture ) {\r\n\r\n\t\t\t\tif ( planeMesh === undefined ) {\r\n\r\n\t\t\t\t\tplaneMesh = new Mesh(\r\n\t\t\t\t\t\tnew PlaneBufferGeometry( 2, 2 ),\r\n\t\t\t\t\t\tnew ShaderMaterial( {\r\n\t\t\t\t\t\t\ttype: 'BackgroundMaterial',\r\n\t\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.background.uniforms ),\r\n\t\t\t\t\t\t\tvertexShader: ShaderLib.background.vertexShader,\r\n\t\t\t\t\t\t\tfragmentShader: ShaderLib.background.fragmentShader,\r\n\t\t\t\t\t\t\tside: FrontSide,\r\n\t\t\t\t\t\t\tdepthTest: false,\r\n\t\t\t\t\t\t\tdepthWrite: false,\r\n\t\t\t\t\t\t\tfog: false\r\n\t\t\t\t\t\t} )\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\tplaneMesh.geometry.deleteAttribute( 'normal' );\r\n\r\n\t\t\t\t\t// enable code injection for non-built-in material\r\n\t\t\t\t\tObject.defineProperty( planeMesh.material, 'map', {\r\n\r\n\t\t\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\t\t\treturn this.uniforms.t2D.value;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\tobjects.update( planeMesh );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tplaneMesh.material.uniforms.t2D.value = background;\r\n\r\n\t\t\t\tif ( background.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tbackground.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tplaneMesh.material.uniforms.uvTransform.value.copy( background.matrix );\r\n\r\n\t\t\t\tif ( currentBackground !== background ||\r\n\t\t\t\t\t currentBackgroundVersion !== background.version ) {\r\n\r\n\t\t\t\t\tplaneMesh.material.needsUpdate = true;\r\n\r\n\t\t\t\t\tcurrentBackground = background;\r\n\t\t\t\t\tcurrentBackgroundVersion = background.version;\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t// push to the pre-sorted opaque render list\r\n\t\t\t\trenderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setClear( color, alpha ) {\r\n\r\n\t\t\tstate.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tgetClearColor: function () {\r\n\r\n\t\t\t\treturn clearColor;\r\n\r\n\t\t\t},\r\n\t\t\tsetClearColor: function ( color, alpha ) {\r\n\r\n\t\t\t\tclearColor.set( color );\r\n\t\t\t\tclearAlpha = alpha !== undefined ? alpha : 1;\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\r\n\t\t\t},\r\n\t\t\tgetClearAlpha: function () {\r\n\r\n\t\t\t\treturn clearAlpha;\r\n\r\n\t\t\t},\r\n\t\t\tsetClearAlpha: function ( alpha ) {\r\n\r\n\t\t\t\tclearAlpha = alpha;\r\n\t\t\t\tsetClear( clearColor, clearAlpha );\r\n\r\n\t\t\t},\r\n\t\t\trender: render\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLBufferRenderer( gl, extensions, info, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tvar mode;\r\n\r\n\t\tfunction setMode( value ) {\r\n\r\n\t\t\tmode = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction render( start, count ) {\r\n\r\n\t\t\tgl.drawArrays( mode, start, count );\r\n\r\n\t\t\tinfo.update( count, mode );\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderInstances( geometry, start, count, primcount ) {\r\n\r\n\t\t\tif ( primcount === 0 ) { return; }\r\n\r\n\t\t\tvar extension, methodName;\r\n\r\n\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\textension = gl;\r\n\t\t\t\tmethodName = 'drawArraysInstanced';\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\r\n\t\t\t\tmethodName = 'drawArraysInstancedANGLE';\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\textension[ methodName ]( mode, start, count, primcount );\r\n\r\n\t\t\tinfo.update( count, mode, primcount );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.setMode = setMode;\r\n\t\tthis.render = render;\r\n\t\tthis.renderInstances = renderInstances;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLCapabilities( gl, extensions, parameters ) {\r\n\r\n\t\tvar maxAnisotropy;\r\n\r\n\t\tfunction getMaxAnisotropy() {\r\n\r\n\t\t\tif ( maxAnisotropy !== undefined ) { return maxAnisotropy; }\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\r\n\r\n\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\tmaxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmaxAnisotropy = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn maxAnisotropy;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getMaxPrecision( precision ) {\r\n\r\n\t\t\tif ( precision === 'highp' ) {\r\n\r\n\t\t\t\tif ( gl.getShaderPrecisionFormat( 35633, 36338 ).precision > 0 &&\r\n\t\t\t\t\tgl.getShaderPrecisionFormat( 35632, 36338 ).precision > 0 ) {\r\n\r\n\t\t\t\t\treturn 'highp';\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tprecision = 'mediump';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( precision === 'mediump' ) {\r\n\r\n\t\t\t\tif ( gl.getShaderPrecisionFormat( 35633, 36337 ).precision > 0 &&\r\n\t\t\t\t\tgl.getShaderPrecisionFormat( 35632, 36337 ).precision > 0 ) {\r\n\r\n\t\t\t\t\treturn 'mediump';\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 'lowp';\r\n\r\n\t\t}\r\n\r\n\t\t/* eslint-disable no-undef */\r\n\t\tvar isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||\r\n\t\t\t( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );\r\n\t\t/* eslint-enable no-undef */\r\n\r\n\t\tvar precision = parameters.precision !== undefined ? parameters.precision : 'highp';\r\n\t\tvar maxPrecision = getMaxPrecision( precision );\r\n\r\n\t\tif ( maxPrecision !== precision ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );\r\n\t\t\tprecision = maxPrecision;\r\n\r\n\t\t}\r\n\r\n\t\tvar logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;\r\n\r\n\t\tvar maxTextures = gl.getParameter( 34930 );\r\n\t\tvar maxVertexTextures = gl.getParameter( 35660 );\r\n\t\tvar maxTextureSize = gl.getParameter( 3379 );\r\n\t\tvar maxCubemapSize = gl.getParameter( 34076 );\r\n\r\n\t\tvar maxAttributes = gl.getParameter( 34921 );\r\n\t\tvar maxVertexUniforms = gl.getParameter( 36347 );\r\n\t\tvar maxVaryings = gl.getParameter( 36348 );\r\n\t\tvar maxFragmentUniforms = gl.getParameter( 36349 );\r\n\r\n\t\tvar vertexTextures = maxVertexTextures > 0;\r\n\t\tvar floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );\r\n\t\tvar floatVertexTextures = vertexTextures && floatFragmentTextures;\r\n\r\n\t\tvar maxSamples = isWebGL2 ? gl.getParameter( 36183 ) : 0;\r\n\r\n\t\treturn {\r\n\r\n\t\t\tisWebGL2: isWebGL2,\r\n\r\n\t\t\tgetMaxAnisotropy: getMaxAnisotropy,\r\n\t\t\tgetMaxPrecision: getMaxPrecision,\r\n\r\n\t\t\tprecision: precision,\r\n\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\r\n\r\n\t\t\tmaxTextures: maxTextures,\r\n\t\t\tmaxVertexTextures: maxVertexTextures,\r\n\t\t\tmaxTextureSize: maxTextureSize,\r\n\t\t\tmaxCubemapSize: maxCubemapSize,\r\n\r\n\t\t\tmaxAttributes: maxAttributes,\r\n\t\t\tmaxVertexUniforms: maxVertexUniforms,\r\n\t\t\tmaxVaryings: maxVaryings,\r\n\t\t\tmaxFragmentUniforms: maxFragmentUniforms,\r\n\r\n\t\t\tvertexTextures: vertexTextures,\r\n\t\t\tfloatFragmentTextures: floatFragmentTextures,\r\n\t\t\tfloatVertexTextures: floatVertexTextures,\r\n\r\n\t\t\tmaxSamples: maxSamples\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction WebGLClipping() {\r\n\r\n\t\tvar scope = this,\r\n\r\n\t\t\tglobalState = null,\r\n\t\t\tnumGlobalPlanes = 0,\r\n\t\t\tlocalClippingEnabled = false,\r\n\t\t\trenderingShadows = false,\r\n\r\n\t\t\tplane = new Plane(),\r\n\t\t\tviewNormalMatrix = new Matrix3(),\r\n\r\n\t\t\tuniform = { value: null, needsUpdate: false };\r\n\r\n\t\tthis.uniform = uniform;\r\n\t\tthis.numPlanes = 0;\r\n\t\tthis.numIntersection = 0;\r\n\r\n\t\tthis.init = function ( planes, enableLocalClipping, camera ) {\r\n\r\n\t\t\tvar enabled =\r\n\t\t\t\tplanes.length !== 0 ||\r\n\t\t\t\tenableLocalClipping ||\r\n\t\t\t\t// enable state of previous frame - the clipping code has to\r\n\t\t\t\t// run another frame in order to reset the state:\r\n\t\t\t\tnumGlobalPlanes !== 0 ||\r\n\t\t\t\tlocalClippingEnabled;\r\n\r\n\t\t\tlocalClippingEnabled = enableLocalClipping;\r\n\r\n\t\t\tglobalState = projectPlanes( planes, camera, 0 );\r\n\t\t\tnumGlobalPlanes = planes.length;\r\n\r\n\t\t\treturn enabled;\r\n\r\n\t\t};\r\n\r\n\t\tthis.beginShadows = function () {\r\n\r\n\t\t\trenderingShadows = true;\r\n\t\t\tprojectPlanes( null );\r\n\r\n\t\t};\r\n\r\n\t\tthis.endShadows = function () {\r\n\r\n\t\t\trenderingShadows = false;\r\n\t\t\tresetGlobalState();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {\r\n\r\n\t\t\tif ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {\r\n\r\n\t\t\t\t// there's no local clipping\r\n\r\n\t\t\t\tif ( renderingShadows ) {\r\n\r\n\t\t\t\t\t// there's no global clipping\r\n\r\n\t\t\t\t\tprojectPlanes( null );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tresetGlobalState();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar nGlobal = renderingShadows ? 0 : numGlobalPlanes,\r\n\t\t\t\t\tlGlobal = nGlobal * 4,\r\n\r\n\t\t\t\t\tdstArray = cache.clippingState || null;\r\n\r\n\t\t\t\tuniform.value = dstArray; // ensure unique state\r\n\r\n\t\t\t\tdstArray = projectPlanes( planes, camera, lGlobal, fromCache );\r\n\r\n\t\t\t\tfor ( var i = 0; i !== lGlobal; ++ i ) {\r\n\r\n\t\t\t\t\tdstArray[ i ] = globalState[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcache.clippingState = dstArray;\r\n\t\t\t\tthis.numIntersection = clipIntersection ? this.numPlanes : 0;\r\n\t\t\t\tthis.numPlanes += nGlobal;\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t};\r\n\r\n\t\tfunction resetGlobalState() {\r\n\r\n\t\t\tif ( uniform.value !== globalState ) {\r\n\r\n\t\t\t\tuniform.value = globalState;\r\n\t\t\t\tuniform.needsUpdate = numGlobalPlanes > 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.numPlanes = numGlobalPlanes;\r\n\t\t\tscope.numIntersection = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction projectPlanes( planes, camera, dstOffset, skipTransform ) {\r\n\r\n\t\t\tvar nPlanes = planes !== null ? planes.length : 0,\r\n\t\t\t\tdstArray = null;\r\n\r\n\t\t\tif ( nPlanes !== 0 ) {\r\n\r\n\t\t\t\tdstArray = uniform.value;\r\n\r\n\t\t\t\tif ( skipTransform !== true || dstArray === null ) {\r\n\r\n\t\t\t\t\tvar flatSize = dstOffset + nPlanes * 4,\r\n\t\t\t\t\t\tviewMatrix = camera.matrixWorldInverse;\r\n\r\n\t\t\t\t\tviewNormalMatrix.getNormalMatrix( viewMatrix );\r\n\r\n\t\t\t\t\tif ( dstArray === null || dstArray.length < flatSize ) {\r\n\r\n\t\t\t\t\t\tdstArray = new Float32Array( flatSize );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tfor ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {\r\n\r\n\t\t\t\t\t\tplane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );\r\n\r\n\t\t\t\t\t\tplane.normal.toArray( dstArray, i4 );\r\n\t\t\t\t\t\tdstArray[ i4 + 3 ] = plane.constant;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniform.value = dstArray;\r\n\t\t\t\tuniform.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.numPlanes = nPlanes;\r\n\r\n\t\t\treturn dstArray;\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLExtensions( gl ) {\r\n\r\n\t\tvar extensions = {};\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: function ( name ) {\r\n\r\n\t\t\t\tif ( extensions[ name ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn extensions[ name ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar extension;\r\n\r\n\t\t\t\tswitch ( name ) {\r\n\r\n\t\t\t\t\tcase 'WEBGL_depth_texture':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'EXT_texture_filter_anisotropic':\r\n\t\t\t\t\t\textension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'WEBGL_compressed_texture_s3tc':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'WEBGL_compressed_texture_pvrtc':\r\n\t\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\t\t\t\t\t\textension = gl.getExtension( name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\textensions[ name ] = extension;\r\n\r\n\t\t\t\treturn extension;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLGeometries( gl, attributes, info ) {\r\n\r\n\t\tvar geometries = new WeakMap();\r\n\t\tvar wireframeAttributes = new WeakMap();\r\n\r\n\t\tfunction onGeometryDispose( event ) {\r\n\r\n\t\t\tvar geometry = event.target;\r\n\t\t\tvar buffergeometry = geometries.get( geometry );\r\n\r\n\t\t\tif ( buffergeometry.index !== null ) {\r\n\r\n\t\t\t\tattributes.remove( buffergeometry.index );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var name in buffergeometry.attributes ) {\r\n\r\n\t\t\t\tattributes.remove( buffergeometry.attributes[ name ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.removeEventListener( 'dispose', onGeometryDispose );\r\n\r\n\t\t\tgeometries.delete( geometry );\r\n\r\n\t\t\tvar attribute = wireframeAttributes.get( buffergeometry );\r\n\r\n\t\t\tif ( attribute ) {\r\n\r\n\t\t\t\tattributes.remove( attribute );\r\n\t\t\t\twireframeAttributes.delete( buffergeometry );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tinfo.memory.geometries --;\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( object, geometry ) {\r\n\r\n\t\t\tvar buffergeometry = geometries.get( geometry );\r\n\r\n\t\t\tif ( buffergeometry ) { return buffergeometry; }\r\n\r\n\t\t\tgeometry.addEventListener( 'dispose', onGeometryDispose );\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tbuffergeometry = geometry;\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tif ( geometry._bufferGeometry === undefined ) {\r\n\r\n\t\t\t\t\tgeometry._bufferGeometry = new BufferGeometry().setFromObject( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbuffergeometry = geometry._bufferGeometry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometries.set( geometry, buffergeometry );\r\n\r\n\t\t\tinfo.memory.geometries ++;\r\n\r\n\t\t\treturn buffergeometry;\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( geometry ) {\r\n\r\n\t\t\tvar index = geometry.index;\r\n\t\t\tvar geometryAttributes = geometry.attributes;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tattributes.update( index, 34963 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var name in geometryAttributes ) {\r\n\r\n\t\t\t\tattributes.update( geometryAttributes[ name ], 34962 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// morph targets\r\n\r\n\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\r\n\t\t\tfor ( var name in morphAttributes ) {\r\n\r\n\t\t\t\tvar array = morphAttributes[ name ];\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tattributes.update( array[ i ], 34962 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateWireframeAttribute( geometry ) {\r\n\r\n\t\t\tvar indices = [];\r\n\r\n\t\t\tvar geometryIndex = geometry.index;\r\n\t\t\tvar geometryPosition = geometry.attributes.position;\r\n\t\t\tvar version = 0;\r\n\r\n\t\t\tif ( geometryIndex !== null ) {\r\n\r\n\t\t\t\tvar array = geometryIndex.array;\r\n\t\t\t\tversion = geometryIndex.version;\r\n\r\n\t\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\tvar a = array[ i + 0 ];\r\n\t\t\t\t\tvar b = array[ i + 1 ];\r\n\t\t\t\t\tvar c = array[ i + 2 ];\r\n\r\n\t\t\t\t\tindices.push( a, b, b, c, c, a );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar array = geometryPosition.array;\r\n\t\t\t\tversion = geometryPosition.version;\r\n\r\n\t\t\t\tfor ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {\r\n\r\n\t\t\t\t\tvar a = i + 0;\r\n\t\t\t\t\tvar b = i + 1;\r\n\t\t\t\t\tvar c = i + 2;\r\n\r\n\t\t\t\t\tindices.push( a, b, b, c, c, a );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );\r\n\t\t\tattribute.version = version;\r\n\r\n\t\t\tattributes.update( attribute, 34963 );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar previousAttribute = wireframeAttributes.get( geometry );\r\n\r\n\t\t\tif ( previousAttribute ) { attributes.remove( previousAttribute ); }\r\n\r\n\t\t\t//\r\n\r\n\t\t\twireframeAttributes.set( geometry, attribute );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getWireframeAttribute( geometry ) {\r\n\r\n\t\t\tvar currentAttribute = wireframeAttributes.get( geometry );\r\n\r\n\t\t\tif ( currentAttribute ) {\r\n\r\n\t\t\t\tvar geometryIndex = geometry.index;\r\n\r\n\t\t\t\tif ( geometryIndex !== null ) {\r\n\r\n\t\t\t\t\t// if the attribute is obsolete, create a new one\r\n\r\n\t\t\t\t\tif ( currentAttribute.version < geometryIndex.version ) {\r\n\r\n\t\t\t\t\t\tupdateWireframeAttribute( geometry );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tupdateWireframeAttribute( geometry );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn wireframeAttributes.get( geometry );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: get,\r\n\t\t\tupdate: update,\r\n\r\n\t\t\tgetWireframeAttribute: getWireframeAttribute\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tvar mode;\r\n\r\n\t\tfunction setMode( value ) {\r\n\r\n\t\t\tmode = value;\r\n\r\n\t\t}\r\n\r\n\t\tvar type, bytesPerElement;\r\n\r\n\t\tfunction setIndex( value ) {\r\n\r\n\t\t\ttype = value.type;\r\n\t\t\tbytesPerElement = value.bytesPerElement;\r\n\r\n\t\t}\r\n\r\n\t\tfunction render( start, count ) {\r\n\r\n\t\t\tgl.drawElements( mode, count, type, start * bytesPerElement );\r\n\r\n\t\t\tinfo.update( count, mode );\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderInstances( geometry, start, count, primcount ) {\r\n\r\n\t\t\tif ( primcount === 0 ) { return; }\r\n\r\n\t\t\tvar extension, methodName;\r\n\r\n\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\textension = gl;\r\n\t\t\t\tmethodName = 'drawElementsInstanced';\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\r\n\t\t\t\tmethodName = 'drawElementsInstancedANGLE';\r\n\r\n\t\t\t\tif ( extension === null ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\textension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );\r\n\r\n\t\t\tinfo.update( count, mode, primcount );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.setMode = setMode;\r\n\t\tthis.setIndex = setIndex;\r\n\t\tthis.render = render;\r\n\t\tthis.renderInstances = renderInstances;\r\n\r\n\t}\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WebGLInfo( gl ) {\r\n\r\n\t\tvar memory = {\r\n\t\t\tgeometries: 0,\r\n\t\t\ttextures: 0\r\n\t\t};\r\n\r\n\t\tvar render = {\r\n\t\t\tframe: 0,\r\n\t\t\tcalls: 0,\r\n\t\t\ttriangles: 0,\r\n\t\t\tpoints: 0,\r\n\t\t\tlines: 0\r\n\t\t};\r\n\r\n\t\tfunction update( count, mode, instanceCount ) {\r\n\r\n\t\t\tinstanceCount = instanceCount || 1;\r\n\r\n\t\t\trender.calls ++;\r\n\r\n\t\t\tswitch ( mode ) {\r\n\r\n\t\t\t\tcase 4:\r\n\t\t\t\t\trender.triangles += instanceCount * ( count / 3 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 1:\r\n\t\t\t\t\trender.lines += instanceCount * ( count / 2 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 3:\r\n\t\t\t\t\trender.lines += instanceCount * ( count - 1 );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 2:\r\n\t\t\t\t\trender.lines += instanceCount * count;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 0:\r\n\t\t\t\t\trender.points += instanceCount * count;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tconsole.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction reset() {\r\n\r\n\t\t\trender.frame ++;\r\n\t\t\trender.calls = 0;\r\n\t\t\trender.triangles = 0;\r\n\t\t\trender.points = 0;\r\n\t\t\trender.lines = 0;\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tmemory: memory,\r\n\t\t\trender: render,\r\n\t\t\tprograms: null,\r\n\t\t\tautoReset: true,\r\n\t\t\treset: reset,\r\n\t\t\tupdate: update\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction absNumericalSort( a, b ) {\r\n\r\n\t\treturn Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );\r\n\r\n\t}\r\n\r\n\tfunction WebGLMorphtargets( gl ) {\r\n\r\n\t\tvar influencesList = {};\r\n\t\tvar morphInfluences = new Float32Array( 8 );\r\n\r\n\t\tfunction update( object, geometry, material, program ) {\r\n\r\n\t\t\tvar objectInfluences = object.morphTargetInfluences;\r\n\r\n\t\t\t// When object doesn't have morph target influences defined, we treat it as a 0-length array\r\n\t\t\t// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences\r\n\r\n\t\t\tvar length = objectInfluences === undefined ? 0 : objectInfluences.length;\r\n\r\n\t\t\tvar influences = influencesList[ geometry.id ];\r\n\r\n\t\t\tif ( influences === undefined ) {\r\n\r\n\t\t\t\t// initialise list\r\n\r\n\t\t\t\tinfluences = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\t\tinfluences[ i ] = [ i, 0 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tinfluencesList[ geometry.id ] = influences;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphTargets = material.morphTargets && geometry.morphAttributes.position;\r\n\t\t\tvar morphNormals = material.morphNormals && geometry.morphAttributes.normal;\r\n\r\n\t\t\t// Remove current morphAttributes\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tif ( influence[ 1 ] !== 0 ) {\r\n\r\n\t\t\t\t\tif ( morphTargets ) { geometry.deleteAttribute( 'morphTarget' + i ); }\r\n\t\t\t\t\tif ( morphNormals ) { geometry.deleteAttribute( 'morphNormal' + i ); }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Collect influences\r\n\r\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tinfluence[ 0 ] = i;\r\n\t\t\t\tinfluence[ 1 ] = objectInfluences[ i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tinfluences.sort( absNumericalSort );\r\n\r\n\t\t\t// Add morphAttributes\r\n\r\n\t\t\tvar morphInfluencesSum = 0;\r\n\r\n\t\t\tfor ( var i = 0; i < 8; i ++ ) {\r\n\r\n\t\t\t\tvar influence = influences[ i ];\r\n\r\n\t\t\t\tif ( influence ) {\r\n\r\n\t\t\t\t\tvar index = influence[ 0 ];\r\n\t\t\t\t\tvar value = influence[ 1 ];\r\n\r\n\t\t\t\t\tif ( value ) {\r\n\r\n\t\t\t\t\t\tif ( morphTargets ) { geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] ); }\r\n\t\t\t\t\t\tif ( morphNormals ) { geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] ); }\r\n\r\n\t\t\t\t\t\tmorphInfluences[ i ] = value;\r\n\t\t\t\t\t\tmorphInfluencesSum += value;\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmorphInfluences[ i ] = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// GLSL shader uses formula baseinfluence * base + sum(target * influence)\r\n\t\t\t// This allows us to switch between absolute morphs and relative morphs without changing shader code\r\n\t\t\t// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)\r\n\t\t\tvar morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;\r\n\r\n\t\t\tprogram.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );\r\n\t\t\tprogram.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tupdate: update\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLObjects( gl, geometries, attributes, info ) {\r\n\r\n\t\tvar updateList = {};\r\n\r\n\t\tfunction update( object ) {\r\n\r\n\t\t\tvar frame = info.render.frame;\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\t\t\tvar buffergeometry = geometries.get( object, geometry );\r\n\r\n\t\t\t// Update once per frame\r\n\r\n\t\t\tif ( updateList[ buffergeometry.id ] !== frame ) {\r\n\r\n\t\t\t\tif ( geometry.isGeometry ) {\r\n\r\n\t\t\t\t\tbuffergeometry.updateFromObject( object );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometries.update( buffergeometry );\r\n\r\n\t\t\t\tupdateList[ buffergeometry.id ] = frame;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.isInstancedMesh ) {\r\n\r\n\t\t\t\tattributes.update( object.instanceMatrix, 34962 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn buffergeometry;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tupdateList = {};\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tupdate: update,\r\n\t\t\tdispose: dispose\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\r\n\r\n\t\timages = images !== undefined ? images : [];\r\n\t\tmapping = mapping !== undefined ? mapping : CubeReflectionMapping;\r\n\t\tformat = format !== undefined ? format : RGBFormat;\r\n\r\n\t\tTexture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.flipY = false;\r\n\r\n\t}\r\n\r\n\tCubeTexture.prototype = Object.create( Texture.prototype );\r\n\tCubeTexture.prototype.constructor = CubeTexture;\r\n\r\n\tCubeTexture.prototype.isCubeTexture = true;\r\n\r\n\tObject.defineProperty( CubeTexture.prototype, 'images', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\treturn this.image;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tthis.image = value;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction DataTexture2DArray( data, width, height, depth ) {\r\n\r\n\t\tTexture.call( this, null );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\r\n\r\n\t\tthis.magFilter = NearestFilter;\r\n\t\tthis.minFilter = NearestFilter;\r\n\r\n\t\tthis.wrapR = ClampToEdgeWrapping;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tDataTexture2DArray.prototype = Object.create( Texture.prototype );\r\n\tDataTexture2DArray.prototype.constructor = DataTexture2DArray;\r\n\tDataTexture2DArray.prototype.isDataTexture2DArray = true;\n\n\t/**\r\n\t * @author Artur Trzesiok\r\n\t */\r\n\r\n\tfunction DataTexture3D( data, width, height, depth ) {\r\n\r\n\t\t// We're going to add .setXXX() methods for setting properties later.\r\n\t\t// Users can still set in DataTexture3D directly.\r\n\t\t//\r\n\t\t//\tvar texture = new THREE.DataTexture3D( data, width, height, depth );\r\n\t\t// \ttexture.anisotropy = 16;\r\n\t\t//\r\n\t\t// See #14839\r\n\r\n\t\tTexture.call( this, null );\r\n\r\n\t\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\r\n\r\n\t\tthis.magFilter = NearestFilter;\r\n\t\tthis.minFilter = NearestFilter;\r\n\r\n\t\tthis.wrapR = ClampToEdgeWrapping;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\t\tthis.flipY = false;\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\r\n\t}\r\n\r\n\tDataTexture3D.prototype = Object.create( Texture.prototype );\r\n\tDataTexture3D.prototype.constructor = DataTexture3D;\r\n\tDataTexture3D.prototype.isDataTexture3D = true;\n\n\t/**\r\n\t * @author tschw\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * Uniforms of a program.\r\n\t * Those form a tree structure with a special top-level container for the root,\r\n\t * which you get by calling 'new WebGLUniforms( gl, program )'.\r\n\t *\r\n\t *\r\n\t * Properties of inner nodes including the top-level container:\r\n\t *\r\n\t * .seq - array of nested uniforms\r\n\t * .map - nested uniforms by name\r\n\t *\r\n\t *\r\n\t * Methods of all nodes except the top-level container:\r\n\t *\r\n\t * .setValue( gl, value, [textures] )\r\n\t *\r\n\t * \t\tuploads a uniform value(s)\r\n\t * \tthe 'textures' parameter is needed for sampler uniforms\r\n\t *\r\n\t *\r\n\t * Static methods of the top-level container (textures factorizations):\r\n\t *\r\n\t * .upload( gl, seq, values, textures )\r\n\t *\r\n\t * \t\tsets uniforms in 'seq' to 'values[id].value'\r\n\t *\r\n\t * .seqWithValue( seq, values ) : filteredSeq\r\n\t *\r\n\t * \t\tfilters 'seq' entries with corresponding entry in values\r\n\t *\r\n\t *\r\n\t * Methods of the top-level container (textures factorizations):\r\n\t *\r\n\t * .setValue( gl, name, value, textures )\r\n\t *\r\n\t * \t\tsets uniform with name 'name' to 'value'\r\n\t *\r\n\t * .setOptional( gl, obj, prop )\r\n\t *\r\n\t * \t\tlike .set for an optional property of the object\r\n\t *\r\n\t */\r\n\r\n\tvar emptyTexture = new Texture();\r\n\tvar emptyTexture2dArray = new DataTexture2DArray();\r\n\tvar emptyTexture3d = new DataTexture3D();\r\n\tvar emptyCubeTexture = new CubeTexture();\r\n\r\n\t// --- Utilities ---\r\n\r\n\t// Array Caches (provide typed arrays for temporary by size)\r\n\r\n\tvar arrayCacheF32 = [];\r\n\tvar arrayCacheI32 = [];\r\n\r\n\t// Float32Array caches used for uploading Matrix uniforms\r\n\r\n\tvar mat4array = new Float32Array( 16 );\r\n\tvar mat3array = new Float32Array( 9 );\r\n\tvar mat2array = new Float32Array( 4 );\r\n\r\n\t// Flattening for arrays of vectors and matrices\r\n\r\n\tfunction flatten( array, nBlocks, blockSize ) {\r\n\r\n\t\tvar firstElem = array[ 0 ];\r\n\r\n\t\tif ( firstElem <= 0 || firstElem > 0 ) { return array; }\r\n\t\t// unoptimized: ! isNaN( firstElem )\r\n\t\t// see http://jacksondunstan.com/articles/983\r\n\r\n\t\tvar n = nBlocks * blockSize,\r\n\t\t\tr = arrayCacheF32[ n ];\r\n\r\n\t\tif ( r === undefined ) {\r\n\r\n\t\t\tr = new Float32Array( n );\r\n\t\t\tarrayCacheF32[ n ] = r;\r\n\r\n\t\t}\r\n\r\n\t\tif ( nBlocks !== 0 ) {\r\n\r\n\t\t\tfirstElem.toArray( r, 0 );\r\n\r\n\t\t\tfor ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {\r\n\r\n\t\t\t\toffset += blockSize;\r\n\t\t\t\tarray[ i ].toArray( r, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn r;\r\n\r\n\t}\r\n\r\n\tfunction arraysEqual( a, b ) {\r\n\r\n\t\tif ( a.length !== b.length ) { return false; }\r\n\r\n\t\tfor ( var i = 0, l = a.length; i < l; i ++ ) {\r\n\r\n\t\t\tif ( a[ i ] !== b[ i ] ) { return false; }\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\tfunction copyArray( a, b ) {\r\n\r\n\t\tfor ( var i = 0, l = b.length; i < l; i ++ ) {\r\n\r\n\t\t\ta[ i ] = b[ i ];\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Texture unit allocation\r\n\r\n\tfunction allocTexUnits( textures, n ) {\r\n\r\n\t\tvar r = arrayCacheI32[ n ];\r\n\r\n\t\tif ( r === undefined ) {\r\n\r\n\t\t\tr = new Int32Array( n );\r\n\t\t\tarrayCacheI32[ n ] = r;\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i )\r\n\t\t\t{ r[ i ] = textures.allocateTextureUnit(); }\r\n\r\n\t\treturn r;\r\n\r\n\t}\r\n\r\n\t// --- Setters ---\r\n\r\n\t// Note: Defining these methods externally, because they come in a bunch\r\n\t// and this way their names minify.\r\n\r\n\t// Single scalar\r\n\r\n\tfunction setValueV1f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( cache[ 0 ] === v ) { return; }\r\n\r\n\t\tgl.uniform1f( this.addr, v );\r\n\r\n\t\tcache[ 0 ] = v;\r\n\r\n\t}\r\n\r\n\t// Single float vector (from flat array or THREE.VectorN)\r\n\r\n\tfunction setValueV2f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {\r\n\r\n\t\t\t\tgl.uniform2f( this.addr, v.x, v.y );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform2fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueV3f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {\r\n\r\n\t\t\t\tgl.uniform3f( this.addr, v.x, v.y, v.z );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\t\t\t\tcache[ 2 ] = v.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( v.r !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {\r\n\r\n\t\t\t\tgl.uniform3f( this.addr, v.r, v.g, v.b );\r\n\r\n\t\t\t\tcache[ 0 ] = v.r;\r\n\t\t\t\tcache[ 1 ] = v.g;\r\n\t\t\t\tcache[ 2 ] = v.b;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform3fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueV4f( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( v.x !== undefined ) {\r\n\r\n\t\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {\r\n\r\n\t\t\t\tgl.uniform4f( this.addr, v.x, v.y, v.z, v.w );\r\n\r\n\t\t\t\tcache[ 0 ] = v.x;\r\n\t\t\t\tcache[ 1 ] = v.y;\r\n\t\t\t\tcache[ 2 ] = v.z;\r\n\t\t\t\tcache[ 3 ] = v.w;\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniform4fv( this.addr, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Single matrix (from flat array or MatrixN)\r\n\r\n\tfunction setValueM2( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix2fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat2array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix2fv( this.addr, false, mat2array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueM3( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix3fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat3array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix3fv( this.addr, false, mat3array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueM4( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar elements = v.elements;\r\n\r\n\t\tif ( elements === undefined ) {\r\n\r\n\t\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\t\tgl.uniformMatrix4fv( this.addr, false, v );\r\n\r\n\t\t\tcopyArray( cache, v );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( arraysEqual( cache, elements ) ) { return; }\r\n\r\n\t\t\tmat4array.set( elements );\r\n\r\n\t\t\tgl.uniformMatrix4fv( this.addr, false, mat4array );\r\n\r\n\t\t\tcopyArray( cache, elements );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Single texture (2D / Cube)\r\n\r\n\tfunction setValueT1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.safeSetTexture2D( v || emptyTexture, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT2DArray1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.setTexture2DArray( v || emptyTexture2dArray, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT3D1( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.setTexture3D( v || emptyTexture3d, unit );\r\n\r\n\t}\r\n\r\n\tfunction setValueT6( gl, v, textures ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\t\tvar unit = textures.allocateTextureUnit();\r\n\r\n\t\tif ( cache[ 0 ] !== unit ) {\r\n\r\n\t\t\tgl.uniform1i( this.addr, unit );\r\n\t\t\tcache[ 0 ] = unit;\r\n\r\n\t\t}\r\n\r\n\t\ttextures.safeSetTextureCube( v || emptyCubeTexture, unit );\r\n\r\n\t}\r\n\r\n\t// Integer / Boolean vectors or arrays thereof (always flat arrays)\r\n\r\n\tfunction setValueV1i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( cache[ 0 ] === v ) { return; }\r\n\r\n\t\tgl.uniform1i( this.addr, v );\r\n\r\n\t\tcache[ 0 ] = v;\r\n\r\n\t}\r\n\r\n\tfunction setValueV2i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform2iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform3iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4i( gl, v ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( arraysEqual( cache, v ) ) { return; }\r\n\r\n\t\tgl.uniform4iv( this.addr, v );\r\n\r\n\t\tcopyArray( cache, v );\r\n\r\n\t}\r\n\r\n\t// Helper to pick the right setter for the singular case\r\n\r\n\tfunction getSingularSetter( type ) {\r\n\r\n\t\tswitch ( type ) {\r\n\r\n\t\t\tcase 0x1406: return setValueV1f; // FLOAT\r\n\t\t\tcase 0x8b50: return setValueV2f; // _VEC2\r\n\t\t\tcase 0x8b51: return setValueV3f; // _VEC3\r\n\t\t\tcase 0x8b52: return setValueV4f; // _VEC4\r\n\r\n\t\t\tcase 0x8b5a: return setValueM2; // _MAT2\r\n\t\t\tcase 0x8b5b: return setValueM3; // _MAT3\r\n\t\t\tcase 0x8b5c: return setValueM4; // _MAT4\r\n\r\n\t\t\tcase 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES\r\n\t\t\tcase 0x8b5f: return setValueT3D1; // SAMPLER_3D\r\n\t\t\tcase 0x8b60: return setValueT6; // SAMPLER_CUBE\r\n\t\t\tcase 0x8DC1: return setValueT2DArray1; // SAMPLER_2D_ARRAY\r\n\r\n\t\t\tcase 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL\r\n\t\t\tcase 0x8b53: case 0x8b57: return setValueV2i; // _VEC2\r\n\t\t\tcase 0x8b54: case 0x8b58: return setValueV3i; // _VEC3\r\n\t\t\tcase 0x8b55: case 0x8b59: return setValueV4i; // _VEC4\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Array of scalars\r\n\tfunction setValueV1fArray( gl, v ) {\r\n\r\n\t\tgl.uniform1fv( this.addr, v );\r\n\r\n\t}\r\n\r\n\t// Integer / Boolean vectors or arrays thereof (always flat arrays)\r\n\tfunction setValueV1iArray( gl, v ) {\r\n\r\n\t\tgl.uniform1iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV2iArray( gl, v ) {\r\n\r\n\t\tgl.uniform2iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3iArray( gl, v ) {\r\n\r\n\t\tgl.uniform3iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4iArray( gl, v ) {\r\n\r\n\t\tgl.uniform4iv( this.addr, v );\r\n\r\n\t}\r\n\r\n\r\n\t// Array of vectors (flat or from THREE classes)\r\n\r\n\tfunction setValueV2fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 2 );\r\n\r\n\t\tgl.uniform2fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueV3fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 3 );\r\n\r\n\t\tgl.uniform3fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueV4fArray( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 4 );\r\n\r\n\t\tgl.uniform4fv( this.addr, data );\r\n\r\n\t}\r\n\r\n\t// Array of matrices (flat or from THREE clases)\r\n\r\n\tfunction setValueM2Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 4 );\r\n\r\n\t\tgl.uniformMatrix2fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueM3Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 9 );\r\n\r\n\t\tgl.uniformMatrix3fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\tfunction setValueM4Array( gl, v ) {\r\n\r\n\t\tvar data = flatten( v, this.size, 16 );\r\n\r\n\t\tgl.uniformMatrix4fv( this.addr, false, data );\r\n\r\n\t}\r\n\r\n\t// Array of textures (2D / Cube)\r\n\r\n\tfunction setValueT1Array( gl, v, textures ) {\r\n\r\n\t\tvar n = v.length;\r\n\r\n\t\tvar units = allocTexUnits( textures, n );\r\n\r\n\t\tgl.uniform1iv( this.addr, units );\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i ) {\r\n\r\n\t\t\ttextures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction setValueT6Array( gl, v, textures ) {\r\n\r\n\t\tvar n = v.length;\r\n\r\n\t\tvar units = allocTexUnits( textures, n );\r\n\r\n\t\tgl.uniform1iv( this.addr, units );\r\n\r\n\t\tfor ( var i = 0; i !== n; ++ i ) {\r\n\r\n\t\t\ttextures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Helper to pick the right setter for a pure (bottom-level) array\r\n\r\n\tfunction getPureArraySetter( type ) {\r\n\r\n\t\tswitch ( type ) {\r\n\r\n\t\t\tcase 0x1406: return setValueV1fArray; // FLOAT\r\n\t\t\tcase 0x8b50: return setValueV2fArray; // _VEC2\r\n\t\t\tcase 0x8b51: return setValueV3fArray; // _VEC3\r\n\t\t\tcase 0x8b52: return setValueV4fArray; // _VEC4\r\n\r\n\t\t\tcase 0x8b5a: return setValueM2Array; // _MAT2\r\n\t\t\tcase 0x8b5b: return setValueM3Array; // _MAT3\r\n\t\t\tcase 0x8b5c: return setValueM4Array; // _MAT4\r\n\r\n\t\t\tcase 0x8b5e: return setValueT1Array; // SAMPLER_2D\r\n\t\t\tcase 0x8b60: return setValueT6Array; // SAMPLER_CUBE\r\n\r\n\t\t\tcase 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL\r\n\t\t\tcase 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2\r\n\t\t\tcase 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3\r\n\t\t\tcase 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// --- Uniform Classes ---\r\n\r\n\tfunction SingleUniform( id, activeInfo, addr ) {\r\n\r\n\t\tthis.id = id;\r\n\t\tthis.addr = addr;\r\n\t\tthis.cache = [];\r\n\t\tthis.setValue = getSingularSetter( activeInfo.type );\r\n\r\n\t\t// this.path = activeInfo.name; // DEBUG\r\n\r\n\t}\r\n\r\n\tfunction PureArrayUniform( id, activeInfo, addr ) {\r\n\r\n\t\tthis.id = id;\r\n\t\tthis.addr = addr;\r\n\t\tthis.cache = [];\r\n\t\tthis.size = activeInfo.size;\r\n\t\tthis.setValue = getPureArraySetter( activeInfo.type );\r\n\r\n\t\t// this.path = activeInfo.name; // DEBUG\r\n\r\n\t}\r\n\r\n\tPureArrayUniform.prototype.updateCache = function ( data ) {\r\n\r\n\t\tvar cache = this.cache;\r\n\r\n\t\tif ( data instanceof Float32Array && cache.length !== data.length ) {\r\n\r\n\t\t\tthis.cache = new Float32Array( data.length );\r\n\r\n\t\t}\r\n\r\n\t\tcopyArray( cache, data );\r\n\r\n\t};\r\n\r\n\tfunction StructuredUniform( id ) {\r\n\r\n\t\tthis.id = id;\r\n\r\n\t\tthis.seq = [];\r\n\t\tthis.map = {};\r\n\r\n\t}\r\n\r\n\tStructuredUniform.prototype.setValue = function ( gl, value, textures ) {\r\n\r\n\t\tvar seq = this.seq;\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ];\r\n\t\t\tu.setValue( gl, value[ u.id ], textures );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t// --- Top-level ---\r\n\r\n\t// Parser - builds up the property tree from the path strings\r\n\r\n\tvar RePathPart = /([\\w\\d_]+)(\\])?(\\[|\\.)?/g;\r\n\r\n\t// extracts\r\n\t// \t- the identifier (member name or array index)\r\n\t// - followed by an optional right bracket (found when array index)\r\n\t// - followed by an optional left bracket or dot (type of subscript)\r\n\t//\r\n\t// Note: These portions can be read in a non-overlapping fashion and\r\n\t// allow straightforward parsing of the hierarchy that WebGL encodes\r\n\t// in the uniform names.\r\n\r\n\tfunction addUniform( container, uniformObject ) {\r\n\r\n\t\tcontainer.seq.push( uniformObject );\r\n\t\tcontainer.map[ uniformObject.id ] = uniformObject;\r\n\r\n\t}\r\n\r\n\tfunction parseUniform( activeInfo, addr, container ) {\r\n\r\n\t\tvar path = activeInfo.name,\r\n\t\t\tpathLength = path.length;\r\n\r\n\t\t// reset RegExp object, because of the early exit of a previous run\r\n\t\tRePathPart.lastIndex = 0;\r\n\r\n\t\twhile ( true ) {\r\n\r\n\t\t\tvar match = RePathPart.exec( path ),\r\n\t\t\t\tmatchEnd = RePathPart.lastIndex,\r\n\r\n\t\t\t\tid = match[ 1 ],\r\n\t\t\t\tidIsIndex = match[ 2 ] === ']',\r\n\t\t\t\tsubscript = match[ 3 ];\r\n\r\n\t\t\tif ( idIsIndex ) { id = id | 0; } // convert to integer\r\n\r\n\t\t\tif ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {\r\n\r\n\t\t\t\t// bare name or \"pure\" bottom-level array \"[0]\" suffix\r\n\r\n\t\t\t\taddUniform( container, subscript === undefined ?\r\n\t\t\t\t\tnew SingleUniform( id, activeInfo, addr ) :\r\n\t\t\t\t\tnew PureArrayUniform( id, activeInfo, addr ) );\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// step into inner node / create it in case it doesn't exist\r\n\r\n\t\t\t\tvar map = container.map, next = map[ id ];\r\n\r\n\t\t\t\tif ( next === undefined ) {\r\n\r\n\t\t\t\t\tnext = new StructuredUniform( id );\r\n\t\t\t\t\taddUniform( container, next );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcontainer = next;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// Root Container\r\n\r\n\tfunction WebGLUniforms( gl, program ) {\r\n\r\n\t\tthis.seq = [];\r\n\t\tthis.map = {};\r\n\r\n\t\tvar n = gl.getProgramParameter( program, 35718 );\r\n\r\n\t\tfor ( var i = 0; i < n; ++ i ) {\r\n\r\n\t\t\tvar info = gl.getActiveUniform( program, i ),\r\n\t\t\t\taddr = gl.getUniformLocation( program, info.name );\r\n\r\n\t\t\tparseUniform( info, addr, this );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tWebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {\r\n\r\n\t\tvar u = this.map[ name ];\r\n\r\n\t\tif ( u !== undefined ) { u.setValue( gl, value, textures ); }\r\n\r\n\t};\r\n\r\n\tWebGLUniforms.prototype.setOptional = function ( gl, object, name ) {\r\n\r\n\t\tvar v = object[ name ];\r\n\r\n\t\tif ( v !== undefined ) { this.setValue( gl, name, v ); }\r\n\r\n\t};\r\n\r\n\r\n\t// Static interface\r\n\r\n\tWebGLUniforms.upload = function ( gl, seq, values, textures ) {\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ],\r\n\t\t\t\tv = values[ u.id ];\r\n\r\n\t\t\tif ( v.needsUpdate !== false ) {\r\n\r\n\t\t\t\t// note: always updating when .needsUpdate is undefined\r\n\t\t\t\tu.setValue( gl, v.value, textures );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tWebGLUniforms.seqWithValue = function ( seq, values ) {\r\n\r\n\t\tvar r = [];\r\n\r\n\t\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\r\n\r\n\t\t\tvar u = seq[ i ];\r\n\t\t\tif ( u.id in values ) { r.push( u ); }\r\n\r\n\t\t}\r\n\r\n\t\treturn r;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLShader( gl, type, string ) {\r\n\r\n\t\tvar shader = gl.createShader( type );\r\n\r\n\t\tgl.shaderSource( shader, string );\r\n\t\tgl.compileShader( shader );\r\n\r\n\t\treturn shader;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar programIdCount = 0;\r\n\r\n\tfunction addLineNumbers( string ) {\r\n\r\n\t\tvar lines = string.split( '\\n' );\r\n\r\n\t\tfor ( var i = 0; i < lines.length; i ++ ) {\r\n\r\n\t\t\tlines[ i ] = ( i + 1 ) + ': ' + lines[ i ];\r\n\r\n\t\t}\r\n\r\n\t\treturn lines.join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction getEncodingComponents( encoding ) {\r\n\r\n\t\tswitch ( encoding ) {\r\n\r\n\t\t\tcase LinearEncoding:\r\n\t\t\t\treturn [ 'Linear', '( value )' ];\r\n\t\t\tcase sRGBEncoding:\r\n\t\t\t\treturn [ 'sRGB', '( value )' ];\r\n\t\t\tcase RGBEEncoding:\r\n\t\t\t\treturn [ 'RGBE', '( value )' ];\r\n\t\t\tcase RGBM7Encoding:\r\n\t\t\t\treturn [ 'RGBM', '( value, 7.0 )' ];\r\n\t\t\tcase RGBM16Encoding:\r\n\t\t\t\treturn [ 'RGBM', '( value, 16.0 )' ];\r\n\t\t\tcase RGBDEncoding:\r\n\t\t\t\treturn [ 'RGBD', '( value, 256.0 )' ];\r\n\t\t\tcase GammaEncoding:\r\n\t\t\t\treturn [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];\r\n\t\t\tcase LogLuvEncoding:\r\n\t\t\t\treturn [ 'LogLuv', '( value )' ];\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'unsupported encoding: ' + encoding );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction getShaderErrors( gl, shader, type ) {\r\n\r\n\t\tvar status = gl.getShaderParameter( shader, 35713 );\r\n\t\tvar log = gl.getShaderInfoLog( shader ).trim();\r\n\r\n\t\tif ( status && log === '' ) { return ''; }\r\n\r\n\t\t// --enable-privileged-webgl-extension\r\n\t\t// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );\r\n\r\n\t\tvar source = gl.getShaderSource( shader );\r\n\r\n\t\treturn 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\\n' + log + addLineNumbers( source );\r\n\r\n\t}\r\n\r\n\tfunction getTexelDecodingFunction( functionName, encoding ) {\r\n\r\n\t\tvar components = getEncodingComponents( encoding );\r\n\t\treturn 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';\r\n\r\n\t}\r\n\r\n\tfunction getTexelEncodingFunction( functionName, encoding ) {\r\n\r\n\t\tvar components = getEncodingComponents( encoding );\r\n\t\treturn 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';\r\n\r\n\t}\r\n\r\n\tfunction getToneMappingFunction( functionName, toneMapping ) {\r\n\r\n\t\tvar toneMappingName;\r\n\r\n\t\tswitch ( toneMapping ) {\r\n\r\n\t\t\tcase LinearToneMapping:\r\n\t\t\t\ttoneMappingName = 'Linear';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ReinhardToneMapping:\r\n\t\t\t\ttoneMappingName = 'Reinhard';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Uncharted2ToneMapping:\r\n\t\t\t\ttoneMappingName = 'Uncharted2';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase CineonToneMapping:\r\n\t\t\t\ttoneMappingName = 'OptimizedCineon';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase ACESFilmicToneMapping:\r\n\t\t\t\ttoneMappingName = 'ACESFilmic';\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'unsupported toneMapping: ' + toneMapping );\r\n\r\n\t\t}\r\n\r\n\t\treturn 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';\r\n\r\n\t}\r\n\r\n\tfunction generateExtensions( extensions, parameters, rendererExtensions ) {\r\n\r\n\t\textensions = extensions || {};\r\n\r\n\t\tvar chunks = [\r\n\t\t\t( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '',\r\n\t\t\t( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '',\r\n\t\t\t( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '',\r\n\t\t\t( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : ''\r\n\t\t];\r\n\r\n\t\treturn chunks.filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction generateDefines( defines ) {\r\n\r\n\t\tvar chunks = [];\r\n\r\n\t\tfor ( var name in defines ) {\r\n\r\n\t\t\tvar value = defines[ name ];\r\n\r\n\t\t\tif ( value === false ) { continue; }\r\n\r\n\t\t\tchunks.push( '#define ' + name + ' ' + value );\r\n\r\n\t\t}\r\n\r\n\t\treturn chunks.join( '\\n' );\r\n\r\n\t}\r\n\r\n\tfunction fetchAttributeLocations( gl, program ) {\r\n\r\n\t\tvar attributes = {};\r\n\r\n\t\tvar n = gl.getProgramParameter( program, 35721 );\r\n\r\n\t\tfor ( var i = 0; i < n; i ++ ) {\r\n\r\n\t\t\tvar info = gl.getActiveAttrib( program, i );\r\n\t\t\tvar name = info.name;\r\n\r\n\t\t\t// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );\r\n\r\n\t\t\tattributes[ name ] = gl.getAttribLocation( program, name );\r\n\r\n\t\t}\r\n\r\n\t\treturn attributes;\r\n\r\n\t}\r\n\r\n\tfunction filterEmptyLine( string ) {\r\n\r\n\t\treturn string !== '';\r\n\r\n\t}\r\n\r\n\tfunction replaceLightNums( string, parameters ) {\r\n\r\n\t\treturn string\r\n\t\t\t.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )\r\n\t\t\t.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )\r\n\t\t\t.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )\r\n\t\t\t.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )\r\n\t\t\t.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )\r\n\t\t\t.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )\r\n\t\t\t.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )\r\n\t\t\t.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );\r\n\r\n\t}\r\n\r\n\tfunction replaceClippingPlaneNums( string, parameters ) {\r\n\r\n\t\treturn string\r\n\t\t\t.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )\r\n\t\t\t.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );\r\n\r\n\t}\r\n\r\n\t// Resolve Includes\r\n\r\n\tvar includePattern = /^[ \\t]*#include +<([\\w\\d./]+)>/gm;\r\n\r\n\tfunction resolveIncludes( string ) {\r\n\r\n\t\treturn string.replace( includePattern, includeReplacer );\r\n\r\n\t}\r\n\r\n\tfunction includeReplacer( match, include ) {\r\n\r\n\t\tvar string = ShaderChunk[ include ];\r\n\r\n\t\tif ( string === undefined ) {\r\n\r\n\t\t\tthrow new Error( 'Can not resolve #include <' + include + '>' );\r\n\r\n\t\t}\r\n\r\n\t\treturn resolveIncludes( string );\r\n\r\n\t}\r\n\r\n\t// Unroll Loops\r\n\r\n\tvar loopPattern = /#pragma unroll_loop[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}/g;\r\n\r\n\tfunction unrollLoops( string ) {\r\n\r\n\t\treturn string.replace( loopPattern, loopReplacer );\r\n\r\n\t}\r\n\r\n\tfunction loopReplacer( match, start, end, snippet ) {\r\n\r\n\t\tvar string = '';\r\n\r\n\t\tfor ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {\r\n\r\n\t\t\tstring += snippet\r\n\t\t\t\t.replace( /\\[ i \\]/g, '[ ' + i + ' ]' )\r\n\t\t\t\t.replace( /UNROLLED_LOOP_INDEX/g, i );\r\n\r\n\t\t}\r\n\r\n\t\treturn string;\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction generatePrecision( parameters ) {\r\n\r\n\t\tvar precisionstring = \"precision \" + parameters.precision + \" float;\\nprecision \" + parameters.precision + \" int;\";\r\n\r\n\t\tif ( parameters.precision === \"highp\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define HIGH_PRECISION\";\r\n\r\n\t\t} else if ( parameters.precision === \"mediump\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define MEDIUM_PRECISION\";\r\n\r\n\t\t} else if ( parameters.precision === \"lowp\" ) {\r\n\r\n\t\t\tprecisionstring += \"\\n#define LOW_PRECISION\";\r\n\r\n\t\t}\r\n\r\n\t\treturn precisionstring;\r\n\r\n\t}\r\n\r\n\tfunction generateShadowMapTypeDefine( parameters ) {\r\n\r\n\t\tvar shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';\r\n\r\n\t\tif ( parameters.shadowMapType === PCFShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';\r\n\r\n\t\t} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';\r\n\r\n\t\t} else if ( parameters.shadowMapType === VSMShadowMap ) {\r\n\r\n\t\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';\r\n\r\n\t\t}\r\n\r\n\t\treturn shadowMapTypeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapTypeDefine( parameters ) {\r\n\r\n\t\tvar envMapTypeDefine = 'ENVMAP_TYPE_CUBE';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.envMapMode ) {\r\n\r\n\t\t\t\tcase CubeReflectionMapping:\r\n\t\t\t\tcase CubeRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase CubeUVReflectionMapping:\r\n\t\t\t\tcase CubeUVRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase EquirectangularReflectionMapping:\r\n\t\t\t\tcase EquirectangularRefractionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase SphericalReflectionMapping:\r\n\t\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_SPHERE';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapTypeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapModeDefine( parameters ) {\r\n\r\n\t\tvar envMapModeDefine = 'ENVMAP_MODE_REFLECTION';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.envMapMode ) {\r\n\r\n\t\t\t\tcase CubeRefractionMapping:\r\n\t\t\t\tcase EquirectangularRefractionMapping:\r\n\t\t\t\t\tenvMapModeDefine = 'ENVMAP_MODE_REFRACTION';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapModeDefine;\r\n\r\n\t}\r\n\r\n\tfunction generateEnvMapBlendingDefine( parameters ) {\r\n\r\n\t\tvar envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';\r\n\r\n\t\tif ( parameters.envMap ) {\r\n\r\n\t\t\tswitch ( parameters.combine ) {\r\n\r\n\t\t\t\tcase MultiplyOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase MixOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MIX';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase AddOperation:\r\n\t\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_ADD';\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn envMapBlendingDefine;\r\n\r\n\t}\r\n\r\n\tfunction WebGLProgram( renderer, extensions, cacheKey, material, shader, parameters ) {\r\n\r\n\t\tvar gl = renderer.getContext();\r\n\r\n\t\tvar defines = material.defines;\r\n\r\n\t\tvar vertexShader = shader.vertexShader;\r\n\t\tvar fragmentShader = shader.fragmentShader;\r\n\t\tvar shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );\r\n\t\tvar envMapTypeDefine = generateEnvMapTypeDefine( parameters );\r\n\t\tvar envMapModeDefine = generateEnvMapModeDefine( parameters );\r\n\t\tvar envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );\r\n\r\n\r\n\t\tvar gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;\r\n\r\n\t\tvar customExtensions = parameters.isWebGL2 ? '' : generateExtensions( material.extensions, parameters, extensions );\r\n\r\n\t\tvar customDefines = generateDefines( defines );\r\n\r\n\t\tvar program = gl.createProgram();\r\n\r\n\t\tvar prefixVertex, prefixFragment;\r\n\r\n\t\tvar numMultiviewViews = parameters.numMultiviewViews;\r\n\r\n\t\tif ( material.isRawShaderMaterial ) {\r\n\r\n\t\t\tprefixVertex = [\r\n\r\n\t\t\t\tcustomDefines\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tif ( prefixVertex.length > 0 ) {\r\n\r\n\t\t\t\tprefixVertex += '\\n';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tprefixFragment = [\r\n\r\n\t\t\t\tcustomExtensions,\r\n\t\t\t\tcustomDefines\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tif ( prefixFragment.length > 0 ) {\r\n\r\n\t\t\t\tprefixFragment += '\\n';\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tprefixVertex = [\r\n\r\n\t\t\t\tgeneratePrecision( parameters ),\r\n\r\n\t\t\t\t'#define SHADER_NAME ' + shader.name,\r\n\r\n\t\t\t\tcustomDefines,\r\n\r\n\t\t\t\tparameters.instancing ? '#define USE_INSTANCING' : '',\r\n\t\t\t\tparameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',\r\n\r\n\t\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\r\n\r\n\t\t\t\t'#define MAX_BONES ' + parameters.maxBones,\r\n\t\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\r\n\t\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\r\n\r\n\t\t\t\tparameters.map ? '#define USE_MAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\r\n\t\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\r\n\t\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\r\n\t\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\r\n\t\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\r\n\t\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\r\n\r\n\t\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\r\n\t\t\t\tparameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',\r\n\t\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\r\n\t\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\r\n\t\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\r\n\t\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\r\n\r\n\t\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\r\n\t\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\r\n\t\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\r\n\t\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\r\n\r\n\t\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\r\n\r\n\t\t\t\tparameters.skinning ? '#define USE_SKINNING' : '',\r\n\t\t\t\tparameters.useVertexTexture ? '#define BONE_TEXTURE' : '',\r\n\r\n\t\t\t\tparameters.morphTargets ? '#define USE_MORPHTARGETS' : '',\r\n\t\t\t\tparameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',\r\n\t\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\r\n\t\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\r\n\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\r\n\r\n\t\t\t\tparameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',\r\n\r\n\t\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\r\n\t\t\t\tparameters.logarithmicDepthBuffer && ( parameters.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\r\n\r\n\t\t\t\t'uniform mat4 modelMatrix;',\r\n\t\t\t\t'uniform mat4 modelViewMatrix;',\r\n\t\t\t\t'uniform mat4 projectionMatrix;',\r\n\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t'uniform mat3 normalMatrix;',\r\n\t\t\t\t'uniform vec3 cameraPosition;',\r\n\t\t\t\t'uniform bool isOrthographic;',\r\n\r\n\t\t\t\t'#ifdef USE_INSTANCING',\r\n\r\n\t\t\t\t' attribute mat4 instanceMatrix;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'attribute vec3 position;',\r\n\t\t\t\t'attribute vec3 normal;',\r\n\t\t\t\t'attribute vec2 uv;',\r\n\r\n\t\t\t\t'#ifdef USE_TANGENT',\r\n\r\n\t\t\t\t'\tattribute vec4 tangent;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_COLOR',\r\n\r\n\t\t\t\t'\tattribute vec3 color;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_MORPHTARGETS',\r\n\r\n\t\t\t\t'\tattribute vec3 morphTarget0;',\r\n\t\t\t\t'\tattribute vec3 morphTarget1;',\r\n\t\t\t\t'\tattribute vec3 morphTarget2;',\r\n\t\t\t\t'\tattribute vec3 morphTarget3;',\r\n\r\n\t\t\t\t'\t#ifdef USE_MORPHNORMALS',\r\n\r\n\t\t\t\t'\t\tattribute vec3 morphNormal0;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal1;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal2;',\r\n\t\t\t\t'\t\tattribute vec3 morphNormal3;',\r\n\r\n\t\t\t\t'\t#else',\r\n\r\n\t\t\t\t'\t\tattribute vec3 morphTarget4;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget5;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget6;',\r\n\t\t\t\t'\t\tattribute vec3 morphTarget7;',\r\n\r\n\t\t\t\t'\t#endif',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'#ifdef USE_SKINNING',\r\n\r\n\t\t\t\t'\tattribute vec4 skinIndex;',\r\n\t\t\t\t'\tattribute vec4 skinWeight;',\r\n\r\n\t\t\t\t'#endif',\r\n\r\n\t\t\t\t'\\n'\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t\tprefixFragment = [\r\n\r\n\t\t\t\tcustomExtensions,\r\n\r\n\t\t\t\tgeneratePrecision( parameters ),\r\n\r\n\t\t\t\t'#define SHADER_NAME ' + shader.name,\r\n\r\n\t\t\t\tcustomDefines,\r\n\r\n\t\t\t\tparameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer\r\n\r\n\t\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\r\n\r\n\t\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\r\n\t\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\r\n\r\n\t\t\t\tparameters.map ? '#define USE_MAP' : '',\r\n\t\t\t\tparameters.matcap ? '#define USE_MATCAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapTypeDefine : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\r\n\t\t\t\tparameters.envMap ? '#define ' + envMapBlendingDefine : '',\r\n\t\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\r\n\t\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\r\n\t\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\r\n\t\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\r\n\t\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\r\n\t\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\r\n\t\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\r\n\t\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\r\n\t\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\r\n\t\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\r\n\t\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\r\n\r\n\t\t\t\tparameters.sheen ? '#define USE_SHEEN' : '',\r\n\r\n\t\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\r\n\t\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\r\n\t\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\r\n\t\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\r\n\r\n\t\t\t\tparameters.gradientMap ? '#define USE_GRADIENTMAP' : '',\r\n\r\n\t\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\r\n\r\n\t\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\r\n\t\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\r\n\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\r\n\t\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\r\n\r\n\t\t\t\tparameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',\r\n\r\n\t\t\t\tparameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',\r\n\r\n\t\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\r\n\t\t\t\tparameters.logarithmicDepthBuffer && ( parameters.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\r\n\r\n\t\t\t\t( ( material.extensions ? material.extensions.shaderTextureLOD : false ) || parameters.envMap ) && ( parameters.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',\r\n\r\n\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t'uniform vec3 cameraPosition;',\r\n\t\t\t\t'uniform bool isOrthographic;',\r\n\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below\r\n\t\t\t\t( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',\r\n\r\n\t\t\t\tparameters.dithering ? '#define DITHERING' : '',\r\n\r\n\t\t\t\t( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding || parameters.lightMapEncoding ) ?\r\n\t\t\t\t\tShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below\r\n\t\t\t\tparameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',\r\n\t\t\t\tparameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',\r\n\t\t\t\tparameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',\r\n\t\t\t\tparameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',\r\n\t\t\t\tparameters.lightMapEncoding ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',\r\n\t\t\t\tparameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',\r\n\r\n\t\t\t\tparameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '',\r\n\r\n\t\t\t\t'\\n'\r\n\r\n\t\t\t].filter( filterEmptyLine ).join( '\\n' );\r\n\r\n\t\t}\r\n\r\n\t\tvertexShader = resolveIncludes( vertexShader );\r\n\t\tvertexShader = replaceLightNums( vertexShader, parameters );\r\n\t\tvertexShader = replaceClippingPlaneNums( vertexShader, parameters );\r\n\r\n\t\tfragmentShader = resolveIncludes( fragmentShader );\r\n\t\tfragmentShader = replaceLightNums( fragmentShader, parameters );\r\n\t\tfragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );\r\n\r\n\t\tvertexShader = unrollLoops( vertexShader );\r\n\t\tfragmentShader = unrollLoops( fragmentShader );\r\n\r\n\t\tif ( parameters.isWebGL2 && ! material.isRawShaderMaterial ) {\r\n\r\n\t\t\tvar isGLSL3ShaderMaterial = false;\r\n\r\n\t\t\tvar versionRegex = /^\\s*#version\\s+300\\s+es\\s*\\n/;\r\n\r\n\t\t\tif ( material.isShaderMaterial &&\r\n\t\t\t\tvertexShader.match( versionRegex ) !== null &&\r\n\t\t\t\tfragmentShader.match( versionRegex ) !== null ) {\r\n\r\n\t\t\t\tisGLSL3ShaderMaterial = true;\r\n\r\n\t\t\t\tvertexShader = vertexShader.replace( versionRegex, '' );\r\n\t\t\t\tfragmentShader = fragmentShader.replace( versionRegex, '' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// GLSL 3.0 conversion\r\n\r\n\t\t\tprefixVertex = [\r\n\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t'#define attribute in',\r\n\t\t\t\t'#define varying out',\r\n\t\t\t\t'#define texture2D texture'\r\n\t\t\t].join( '\\n' ) + '\\n' + prefixVertex;\r\n\r\n\t\t\tprefixFragment = [\r\n\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t'#define varying in',\r\n\t\t\t\tisGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',\r\n\t\t\t\tisGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',\r\n\t\t\t\t'#define gl_FragDepthEXT gl_FragDepth',\r\n\t\t\t\t'#define texture2D texture',\r\n\t\t\t\t'#define textureCube texture',\r\n\t\t\t\t'#define texture2DProj textureProj',\r\n\t\t\t\t'#define texture2DLodEXT textureLod',\r\n\t\t\t\t'#define texture2DProjLodEXT textureProjLod',\r\n\t\t\t\t'#define textureCubeLodEXT textureLod',\r\n\t\t\t\t'#define texture2DGradEXT textureGrad',\r\n\t\t\t\t'#define texture2DProjGradEXT textureProjGrad',\r\n\t\t\t\t'#define textureCubeGradEXT textureGrad'\r\n\t\t\t].join( '\\n' ) + '\\n' + prefixFragment;\r\n\r\n\t\t\t// Multiview\r\n\r\n\t\t\tif ( numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\tprefixVertex = prefixVertex.replace(\r\n\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t\t'#extension GL_OVR_multiview2 : require',\r\n\t\t\t\t\t\t'layout(num_views = ' + numMultiviewViews + ') in;',\r\n\t\t\t\t\t\t'#define VIEW_ID gl_ViewID_OVR'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixVertex = prefixVertex.replace(\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 modelViewMatrix;',\r\n\t\t\t\t\t\t'uniform mat4 projectionMatrix;',\r\n\t\t\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t\t\t'uniform mat3 normalMatrix;'\r\n\t\t\t\t\t].join( '\\n' ),\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 modelViewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat4 projectionMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat4 viewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'uniform mat3 normalMatrices[' + numMultiviewViews + '];',\r\n\r\n\t\t\t\t\t\t'#define modelViewMatrix modelViewMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define projectionMatrix projectionMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define viewMatrix viewMatrices[VIEW_ID]',\r\n\t\t\t\t\t\t'#define normalMatrix normalMatrices[VIEW_ID]'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixFragment = prefixFragment.replace(\r\n\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'#version 300 es\\n',\r\n\t\t\t\t\t\t'#extension GL_OVR_multiview2 : require',\r\n\t\t\t\t\t\t'#define VIEW_ID gl_ViewID_OVR'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t\tprefixFragment = prefixFragment.replace(\r\n\t\t\t\t\t'uniform mat4 viewMatrix;',\r\n\t\t\t\t\t[\r\n\t\t\t\t\t\t'uniform mat4 viewMatrices[' + numMultiviewViews + '];',\r\n\t\t\t\t\t\t'#define viewMatrix viewMatrices[VIEW_ID]'\r\n\t\t\t\t\t].join( '\\n' )\r\n\t\t\t\t);\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar vertexGlsl = prefixVertex + vertexShader;\r\n\t\tvar fragmentGlsl = prefixFragment + fragmentShader;\r\n\r\n\t\t// console.log( '*VERTEX*', vertexGlsl );\r\n\t\t// console.log( '*FRAGMENT*', fragmentGlsl );\r\n\r\n\t\tvar glVertexShader = WebGLShader( gl, 35633, vertexGlsl );\r\n\t\tvar glFragmentShader = WebGLShader( gl, 35632, fragmentGlsl );\r\n\r\n\t\tgl.attachShader( program, glVertexShader );\r\n\t\tgl.attachShader( program, glFragmentShader );\r\n\r\n\t\t// Force a particular attribute to index 0.\r\n\r\n\t\tif ( material.index0AttributeName !== undefined ) {\r\n\r\n\t\t\tgl.bindAttribLocation( program, 0, material.index0AttributeName );\r\n\r\n\t\t} else if ( parameters.morphTargets === true ) {\r\n\r\n\t\t\t// programs with morphTargets displace position out of attribute 0\r\n\t\t\tgl.bindAttribLocation( program, 0, 'position' );\r\n\r\n\t\t}\r\n\r\n\t\tgl.linkProgram( program );\r\n\r\n\t\t// check for link errors\r\n\t\tif ( renderer.debug.checkShaderErrors ) {\r\n\r\n\t\t\tvar programLog = gl.getProgramInfoLog( program ).trim();\r\n\t\t\tvar vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();\r\n\t\t\tvar fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();\r\n\r\n\t\t\tvar runnable = true;\r\n\t\t\tvar haveDiagnostics = true;\r\n\r\n\t\t\tif ( gl.getProgramParameter( program, 35714 ) === false ) {\r\n\r\n\t\t\t\trunnable = false;\r\n\r\n\t\t\t\tvar vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );\r\n\t\t\t\tvar fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), '35715', gl.getProgramParameter( program, 35715 ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );\r\n\r\n\t\t\t} else if ( programLog !== '' ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );\r\n\r\n\t\t\t} else if ( vertexLog === '' || fragmentLog === '' ) {\r\n\r\n\t\t\t\thaveDiagnostics = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( haveDiagnostics ) {\r\n\r\n\t\t\t\tthis.diagnostics = {\r\n\r\n\t\t\t\t\trunnable: runnable,\r\n\t\t\t\t\tmaterial: material,\r\n\r\n\t\t\t\t\tprogramLog: programLog,\r\n\r\n\t\t\t\t\tvertexShader: {\r\n\r\n\t\t\t\t\t\tlog: vertexLog,\r\n\t\t\t\t\t\tprefix: prefixVertex\r\n\r\n\t\t\t\t\t},\r\n\r\n\t\t\t\t\tfragmentShader: {\r\n\r\n\t\t\t\t\t\tlog: fragmentLog,\r\n\t\t\t\t\t\tprefix: prefixFragment\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// clean up\r\n\r\n\t\tgl.deleteShader( glVertexShader );\r\n\t\tgl.deleteShader( glFragmentShader );\r\n\r\n\t\t// set up caching for uniform locations\r\n\r\n\t\tvar cachedUniforms;\r\n\r\n\t\tthis.getUniforms = function () {\r\n\r\n\t\t\tif ( cachedUniforms === undefined ) {\r\n\r\n\t\t\t\tcachedUniforms = new WebGLUniforms( gl, program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn cachedUniforms;\r\n\r\n\t\t};\r\n\r\n\t\t// set up caching for attribute locations\r\n\r\n\t\tvar cachedAttributes;\r\n\r\n\t\tthis.getAttributes = function () {\r\n\r\n\t\t\tif ( cachedAttributes === undefined ) {\r\n\r\n\t\t\t\tcachedAttributes = fetchAttributeLocations( gl, program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn cachedAttributes;\r\n\r\n\t\t};\r\n\r\n\t\t// free resource\r\n\r\n\t\tthis.destroy = function () {\r\n\r\n\t\t\tgl.deleteProgram( program );\r\n\t\t\tthis.program = undefined;\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tthis.name = shader.name;\r\n\t\tthis.id = programIdCount ++;\r\n\t\tthis.cacheKey = cacheKey;\r\n\t\tthis.usedTimes = 1;\r\n\t\tthis.program = program;\r\n\t\tthis.vertexShader = glVertexShader;\r\n\t\tthis.fragmentShader = glFragmentShader;\r\n\t\tthis.numMultiviewViews = numMultiviewViews;\r\n\r\n\t\treturn this;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLPrograms( renderer, extensions, capabilities ) {\r\n\r\n\t\tvar programs = [];\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\t\tvar logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;\r\n\t\tvar floatVertexTextures = capabilities.floatVertexTextures;\r\n\t\tvar precision = capabilities.precision;\r\n\t\tvar maxVertexUniforms = capabilities.maxVertexUniforms;\r\n\t\tvar vertexTextures = capabilities.vertexTextures;\r\n\r\n\t\tvar shaderIDs = {\r\n\t\t\tMeshDepthMaterial: 'depth',\r\n\t\t\tMeshDistanceMaterial: 'distanceRGBA',\r\n\t\t\tMeshNormalMaterial: 'normal',\r\n\t\t\tMeshBasicMaterial: 'basic',\r\n\t\t\tMeshLambertMaterial: 'lambert',\r\n\t\t\tMeshPhongMaterial: 'phong',\r\n\t\t\tMeshToonMaterial: 'toon',\r\n\t\t\tMeshStandardMaterial: 'physical',\r\n\t\t\tMeshPhysicalMaterial: 'physical',\r\n\t\t\tMeshMatcapMaterial: 'matcap',\r\n\t\t\tLineBasicMaterial: 'basic',\r\n\t\t\tLineDashedMaterial: 'dashed',\r\n\t\t\tPointsMaterial: 'points',\r\n\t\t\tShadowMaterial: 'shadow',\r\n\t\t\tSpriteMaterial: 'sprite'\r\n\t\t};\r\n\r\n\t\tvar parameterNames = [\r\n\t\t\t\"precision\", \"isWebGL2\", \"supportsVertexTextures\", \"outputEncoding\", \"instancing\", \"numMultiviewViews\",\r\n\t\t\t\"map\", \"mapEncoding\", \"matcap\", \"matcapEncoding\", \"envMap\", \"envMapMode\", \"envMapEncoding\", \"envMapCubeUV\",\r\n\t\t\t\"lightMap\", \"lightMapEncoding\", \"aoMap\", \"emissiveMap\", \"emissiveMapEncoding\", \"bumpMap\", \"normalMap\", \"objectSpaceNormalMap\", \"tangentSpaceNormalMap\", \"clearcoatNormalMap\", \"displacementMap\", \"specularMap\",\r\n\t\t\t\"roughnessMap\", \"metalnessMap\", \"gradientMap\",\r\n\t\t\t\"alphaMap\", \"combine\", \"vertexColors\", \"vertexTangents\", \"vertexUvs\", \"uvsVertexOnly\", \"fog\", \"useFog\", \"fogExp2\",\r\n\t\t\t\"flatShading\", \"sizeAttenuation\", \"logarithmicDepthBuffer\", \"skinning\",\r\n\t\t\t\"maxBones\", \"useVertexTexture\", \"morphTargets\", \"morphNormals\",\r\n\t\t\t\"maxMorphTargets\", \"maxMorphNormals\", \"premultipliedAlpha\",\r\n\t\t\t\"numDirLights\", \"numPointLights\", \"numSpotLights\", \"numHemiLights\", \"numRectAreaLights\",\r\n\t\t\t\"numDirLightShadows\", \"numPointLightShadows\", \"numSpotLightShadows\",\r\n\t\t\t\"shadowMapEnabled\", \"shadowMapType\", \"toneMapping\", 'physicallyCorrectLights',\r\n\t\t\t\"alphaTest\", \"doubleSided\", \"flipSided\", \"numClippingPlanes\", \"numClipIntersection\", \"depthPacking\", \"dithering\",\r\n\t\t\t\"sheen\"\r\n\t\t];\r\n\r\n\r\n\t\tfunction allocateBones( object ) {\r\n\r\n\t\t\tvar skeleton = object.skeleton;\r\n\t\t\tvar bones = skeleton.bones;\r\n\r\n\t\t\tif ( floatVertexTextures ) {\r\n\r\n\t\t\t\treturn 1024;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// default for when object is not specified\r\n\t\t\t\t// ( for example when prebuilding shader to be used with multiple objects )\r\n\t\t\t\t//\r\n\t\t\t\t// - leave some extra space for other uniforms\r\n\t\t\t\t// - limit here is ANGLE's 254 max uniform vectors\r\n\t\t\t\t// (up to 54 should be safe)\r\n\r\n\t\t\t\tvar nVertexUniforms = maxVertexUniforms;\r\n\t\t\t\tvar nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );\r\n\r\n\t\t\t\tvar maxBones = Math.min( nVertexMatrices, bones.length );\r\n\r\n\t\t\t\tif ( maxBones < bones.length ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );\r\n\t\t\t\t\treturn 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn maxBones;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction getTextureEncodingFromMap( map, gammaOverrideLinear ) {\r\n\r\n\t\t\tvar encoding;\r\n\r\n\t\t\tif ( ! map ) {\r\n\r\n\t\t\t\tencoding = LinearEncoding;\r\n\r\n\t\t\t} else if ( map.isTexture ) {\r\n\r\n\t\t\t\tencoding = map.encoding;\r\n\r\n\t\t\t} else if ( map.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\tconsole.warn( \"THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\tencoding = map.texture.encoding;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point.\r\n\t\t\tif ( encoding === LinearEncoding && gammaOverrideLinear ) {\r\n\r\n\t\t\t\tencoding = GammaEncoding;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn encoding;\r\n\r\n\t\t}\r\n\r\n\t\tthis.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) {\r\n\r\n\t\t\tvar shaderID = shaderIDs[ material.type ];\r\n\r\n\t\t\t// heuristics to create shader parameters according to lights in the scene\r\n\t\t\t// (not to blow over maxLights budget)\r\n\r\n\t\t\tvar maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;\r\n\r\n\t\t\tif ( material.precision !== null ) {\r\n\r\n\t\t\t\tprecision = capabilities.getMaxPrecision( material.precision );\r\n\r\n\t\t\t\tif ( precision !== material.precision ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar currentRenderTarget = renderer.getRenderTarget();\r\n\t\t\tvar numMultiviewViews = currentRenderTarget && currentRenderTarget.isWebGLMultiviewRenderTarget ? currentRenderTarget.numViews : 0;\r\n\r\n\t\t\tvar parameters = {\r\n\r\n\t\t\t\tisWebGL2: isWebGL2,\r\n\r\n\t\t\t\tshaderID: shaderID,\r\n\r\n\t\t\t\tprecision: precision,\r\n\r\n\t\t\t\tinstancing: object.isInstancedMesh === true,\r\n\r\n\t\t\t\tsupportsVertexTextures: vertexTextures,\r\n\t\t\t\tnumMultiviewViews: numMultiviewViews,\r\n\t\t\t\toutputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ),\r\n\t\t\t\tmap: !! material.map,\r\n\t\t\t\tmapEncoding: getTextureEncodingFromMap( material.map ),\r\n\t\t\t\tmatcap: !! material.matcap,\r\n\t\t\t\tmatcapEncoding: getTextureEncodingFromMap( material.matcap ),\r\n\t\t\t\tenvMap: !! material.envMap,\r\n\t\t\t\tenvMapMode: material.envMap && material.envMap.mapping,\r\n\t\t\t\tenvMapEncoding: getTextureEncodingFromMap( material.envMap ),\r\n\t\t\t\tenvMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ),\r\n\t\t\t\tlightMap: !! material.lightMap,\r\n\t\t\t\tlightMapEncoding: getTextureEncodingFromMap( material.lightMap ),\r\n\t\t\t\taoMap: !! material.aoMap,\r\n\t\t\t\temissiveMap: !! material.emissiveMap,\r\n\t\t\t\temissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),\r\n\t\t\t\tbumpMap: !! material.bumpMap,\r\n\t\t\t\tnormalMap: !! material.normalMap,\r\n\t\t\t\tobjectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,\r\n\t\t\t\ttangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,\r\n\t\t\t\tclearcoatNormalMap: !! material.clearcoatNormalMap,\r\n\t\t\t\tdisplacementMap: !! material.displacementMap,\r\n\t\t\t\troughnessMap: !! material.roughnessMap,\r\n\t\t\t\tmetalnessMap: !! material.metalnessMap,\r\n\t\t\t\tspecularMap: !! material.specularMap,\r\n\t\t\t\talphaMap: !! material.alphaMap,\r\n\r\n\t\t\t\tgradientMap: !! material.gradientMap,\r\n\r\n\t\t\t\tsheen: !! material.sheen,\r\n\r\n\t\t\t\tcombine: material.combine,\r\n\r\n\t\t\t\tvertexTangents: ( material.normalMap && material.vertexTangents ),\r\n\t\t\t\tvertexColors: material.vertexColors,\r\n\t\t\t\tvertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,\r\n\t\t\t\tuvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,\r\n\r\n\t\t\t\tfog: !! fog,\r\n\t\t\t\tuseFog: material.fog,\r\n\t\t\t\tfogExp2: ( fog && fog.isFogExp2 ),\r\n\r\n\t\t\t\tflatShading: material.flatShading,\r\n\r\n\t\t\t\tsizeAttenuation: material.sizeAttenuation,\r\n\t\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\r\n\r\n\t\t\t\tskinning: material.skinning && maxBones > 0,\r\n\t\t\t\tmaxBones: maxBones,\r\n\t\t\t\tuseVertexTexture: floatVertexTextures,\r\n\r\n\t\t\t\tmorphTargets: material.morphTargets,\r\n\t\t\t\tmorphNormals: material.morphNormals,\r\n\t\t\t\tmaxMorphTargets: renderer.maxMorphTargets,\r\n\t\t\t\tmaxMorphNormals: renderer.maxMorphNormals,\r\n\r\n\t\t\t\tnumDirLights: lights.directional.length,\r\n\t\t\t\tnumPointLights: lights.point.length,\r\n\t\t\t\tnumSpotLights: lights.spot.length,\r\n\t\t\t\tnumRectAreaLights: lights.rectArea.length,\r\n\t\t\t\tnumHemiLights: lights.hemi.length,\r\n\r\n\t\t\t\tnumDirLightShadows: lights.directionalShadowMap.length,\r\n\t\t\t\tnumPointLightShadows: lights.pointShadowMap.length,\r\n\t\t\t\tnumSpotLightShadows: lights.spotShadowMap.length,\r\n\r\n\t\t\t\tnumClippingPlanes: nClipPlanes,\r\n\t\t\t\tnumClipIntersection: nClipIntersection,\r\n\r\n\t\t\t\tdithering: material.dithering,\r\n\r\n\t\t\t\tshadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,\r\n\t\t\t\tshadowMapType: renderer.shadowMap.type,\r\n\r\n\t\t\t\ttoneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,\r\n\t\t\t\tphysicallyCorrectLights: renderer.physicallyCorrectLights,\r\n\r\n\t\t\t\tpremultipliedAlpha: material.premultipliedAlpha,\r\n\r\n\t\t\t\talphaTest: material.alphaTest,\r\n\t\t\t\tdoubleSided: material.side === DoubleSide,\r\n\t\t\t\tflipSided: material.side === BackSide,\r\n\r\n\t\t\t\tdepthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false\r\n\r\n\t\t\t};\r\n\r\n\t\t\treturn parameters;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getProgramCacheKey = function ( material, parameters ) {\r\n\r\n\t\t\tvar array = [];\r\n\r\n\t\t\tif ( parameters.shaderID ) {\r\n\r\n\t\t\t\tarray.push( parameters.shaderID );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tarray.push( material.fragmentShader );\r\n\t\t\t\tarray.push( material.vertexShader );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.defines !== undefined ) {\r\n\r\n\t\t\t\tfor ( var name in material.defines ) {\r\n\r\n\t\t\t\t\tarray.push( name );\r\n\t\t\t\t\tarray.push( material.defines[ name ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < parameterNames.length; i ++ ) {\r\n\r\n\t\t\t\tarray.push( parameters[ parameterNames[ i ] ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tarray.push( material.onBeforeCompile.toString() );\r\n\r\n\t\t\tarray.push( renderer.gammaOutput );\r\n\r\n\t\t\tarray.push( renderer.gammaFactor );\r\n\r\n\t\t\treturn array.join();\r\n\r\n\t\t};\r\n\r\n\t\tthis.acquireProgram = function ( material, shader, parameters, cacheKey ) {\r\n\r\n\t\t\tvar program;\r\n\r\n\t\t\t// Check if code has been already compiled\r\n\t\t\tfor ( var p = 0, pl = programs.length; p < pl; p ++ ) {\r\n\r\n\t\t\t\tvar preexistingProgram = programs[ p ];\r\n\r\n\t\t\t\tif ( preexistingProgram.cacheKey === cacheKey ) {\r\n\r\n\t\t\t\t\tprogram = preexistingProgram;\r\n\t\t\t\t\t++ program.usedTimes;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( program === undefined ) {\r\n\r\n\t\t\t\tprogram = new WebGLProgram( renderer, extensions, cacheKey, material, shader, parameters );\r\n\t\t\t\tprograms.push( program );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn program;\r\n\r\n\t\t};\r\n\r\n\t\tthis.releaseProgram = function ( program ) {\r\n\r\n\t\t\tif ( -- program.usedTimes === 0 ) {\r\n\r\n\t\t\t\t// Remove from unordered set\r\n\t\t\t\tvar i = programs.indexOf( program );\r\n\t\t\t\tprograms[ i ] = programs[ programs.length - 1 ];\r\n\t\t\t\tprograms.pop();\r\n\r\n\t\t\t\t// Free WebGL resources\r\n\t\t\t\tprogram.destroy();\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\t// Exposed for resource monitoring & error feedback via renderer.info:\r\n\t\tthis.programs = programs;\r\n\r\n\t}\n\n\t/**\r\n\t * @author fordacious / fordacious.github.io\r\n\t */\r\n\r\n\tfunction WebGLProperties() {\r\n\r\n\t\tvar properties = new WeakMap();\r\n\r\n\t\tfunction get( object ) {\r\n\r\n\t\t\tvar map = properties.get( object );\r\n\r\n\t\t\tif ( map === undefined ) {\r\n\r\n\t\t\t\tmap = {};\r\n\t\t\t\tproperties.set( object, map );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn map;\r\n\r\n\t\t}\r\n\r\n\t\tfunction remove( object ) {\r\n\r\n\t\t\tproperties.delete( object );\r\n\r\n\t\t}\r\n\r\n\t\tfunction update( object, key, value ) {\r\n\r\n\t\t\tproperties.get( object )[ key ] = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tproperties = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tremove: remove,\r\n\t\t\tupdate: update,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction painterSortStable( a, b ) {\r\n\r\n\t\tif ( a.groupOrder !== b.groupOrder ) {\r\n\r\n\t\t\treturn a.groupOrder - b.groupOrder;\r\n\r\n\t\t} else if ( a.renderOrder !== b.renderOrder ) {\r\n\r\n\t\t\treturn a.renderOrder - b.renderOrder;\r\n\r\n\t\t} else if ( a.program !== b.program ) {\r\n\r\n\t\t\treturn a.program.id - b.program.id;\r\n\r\n\t\t} else if ( a.material.id !== b.material.id ) {\r\n\r\n\t\t\treturn a.material.id - b.material.id;\r\n\r\n\t\t} else if ( a.z !== b.z ) {\r\n\r\n\t\t\treturn a.z - b.z;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn a.id - b.id;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction reversePainterSortStable( a, b ) {\r\n\r\n\t\tif ( a.groupOrder !== b.groupOrder ) {\r\n\r\n\t\t\treturn a.groupOrder - b.groupOrder;\r\n\r\n\t\t} else if ( a.renderOrder !== b.renderOrder ) {\r\n\r\n\t\t\treturn a.renderOrder - b.renderOrder;\r\n\r\n\t\t} else if ( a.z !== b.z ) {\r\n\r\n\t\t\treturn b.z - a.z;\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn a.id - b.id;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\r\n\tfunction WebGLRenderList() {\r\n\r\n\t\tvar renderItems = [];\r\n\t\tvar renderItemsIndex = 0;\r\n\r\n\t\tvar opaque = [];\r\n\t\tvar transparent = [];\r\n\r\n\t\tvar defaultProgram = { id: - 1 };\r\n\r\n\t\tfunction init() {\r\n\r\n\t\t\trenderItemsIndex = 0;\r\n\r\n\t\t\topaque.length = 0;\r\n\t\t\ttransparent.length = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getNextRenderItem( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = renderItems[ renderItemsIndex ];\r\n\r\n\t\t\tif ( renderItem === undefined ) {\r\n\r\n\t\t\t\trenderItem = {\r\n\t\t\t\t\tid: object.id,\r\n\t\t\t\t\tobject: object,\r\n\t\t\t\t\tgeometry: geometry,\r\n\t\t\t\t\tmaterial: material,\r\n\t\t\t\t\tprogram: material.program || defaultProgram,\r\n\t\t\t\t\tgroupOrder: groupOrder,\r\n\t\t\t\t\trenderOrder: object.renderOrder,\r\n\t\t\t\t\tz: z,\r\n\t\t\t\t\tgroup: group\r\n\t\t\t\t};\r\n\r\n\t\t\t\trenderItems[ renderItemsIndex ] = renderItem;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderItem.id = object.id;\r\n\t\t\t\trenderItem.object = object;\r\n\t\t\t\trenderItem.geometry = geometry;\r\n\t\t\t\trenderItem.material = material;\r\n\t\t\t\trenderItem.program = material.program || defaultProgram;\r\n\t\t\t\trenderItem.groupOrder = groupOrder;\r\n\t\t\t\trenderItem.renderOrder = object.renderOrder;\r\n\t\t\t\trenderItem.z = z;\r\n\t\t\t\trenderItem.group = group;\r\n\r\n\t\t\t}\r\n\r\n\t\t\trenderItemsIndex ++;\r\n\r\n\t\t\treturn renderItem;\r\n\r\n\t\t}\r\n\r\n\t\tfunction push( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\r\n\r\n\t\t\t( material.transparent === true ? transparent : opaque ).push( renderItem );\r\n\r\n\t\t}\r\n\r\n\t\tfunction unshift( object, geometry, material, groupOrder, z, group ) {\r\n\r\n\t\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\r\n\r\n\t\t\t( material.transparent === true ? transparent : opaque ).unshift( renderItem );\r\n\r\n\t\t}\r\n\r\n\t\tfunction sort() {\r\n\r\n\t\t\tif ( opaque.length > 1 ) { opaque.sort( painterSortStable ); }\r\n\t\t\tif ( transparent.length > 1 ) { transparent.sort( reversePainterSortStable ); }\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\topaque: opaque,\r\n\t\t\ttransparent: transparent,\r\n\r\n\t\t\tinit: init,\r\n\t\t\tpush: push,\r\n\t\t\tunshift: unshift,\r\n\r\n\t\t\tsort: sort\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction WebGLRenderLists() {\r\n\r\n\t\tvar lists = new WeakMap();\r\n\r\n\t\tfunction onSceneDispose( event ) {\r\n\r\n\t\t\tvar scene = event.target;\r\n\r\n\t\t\tscene.removeEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\tlists.delete( scene );\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( scene, camera ) {\r\n\r\n\t\t\tvar cameras = lists.get( scene );\r\n\t\t\tvar list;\r\n\t\t\tif ( cameras === undefined ) {\r\n\r\n\t\t\t\tlist = new WebGLRenderList();\r\n\t\t\t\tlists.set( scene, new WeakMap() );\r\n\t\t\t\tlists.get( scene ).set( camera, list );\r\n\r\n\t\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tlist = cameras.get( camera );\r\n\t\t\t\tif ( list === undefined ) {\r\n\r\n\t\t\t\t\tlist = new WebGLRenderList();\r\n\t\t\t\t\tcameras.set( camera, list );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn list;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\tlists = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction UniformsCache() {\r\n\r\n\t\tvar lights = {};\r\n\r\n\t\treturn {\r\n\r\n\t\t\tget: function ( light ) {\r\n\r\n\t\t\t\tif ( lights[ light.id ] !== undefined ) {\r\n\r\n\t\t\t\t\treturn lights[ light.id ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar uniforms;\r\n\r\n\t\t\t\tswitch ( light.type ) {\r\n\r\n\t\t\t\t\tcase 'DirectionalLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'SpotLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tdistance: 0,\r\n\t\t\t\t\t\t\tconeCos: 0,\r\n\t\t\t\t\t\t\tpenumbraCos: 0,\r\n\t\t\t\t\t\t\tdecay: 0,\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'PointLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tdistance: 0,\r\n\t\t\t\t\t\t\tdecay: 0,\r\n\r\n\t\t\t\t\t\t\tshadow: false,\r\n\t\t\t\t\t\t\tshadowBias: 0,\r\n\t\t\t\t\t\t\tshadowRadius: 1,\r\n\t\t\t\t\t\t\tshadowMapSize: new Vector2(),\r\n\t\t\t\t\t\t\tshadowCameraNear: 1,\r\n\t\t\t\t\t\t\tshadowCameraFar: 1000\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'HemisphereLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tdirection: new Vector3(),\r\n\t\t\t\t\t\t\tskyColor: new Color(),\r\n\t\t\t\t\t\t\tgroundColor: new Color()\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'RectAreaLight':\r\n\t\t\t\t\t\tuniforms = {\r\n\t\t\t\t\t\t\tcolor: new Color(),\r\n\t\t\t\t\t\t\tposition: new Vector3(),\r\n\t\t\t\t\t\t\thalfWidth: new Vector3(),\r\n\t\t\t\t\t\t\thalfHeight: new Vector3()\r\n\t\t\t\t\t\t\t// TODO (abelnation): set RectAreaLight shadow uniforms\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tlights[ light.id ] = uniforms;\r\n\r\n\t\t\t\treturn uniforms;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tvar nextVersion = 0;\r\n\r\n\tfunction shadowCastingLightsFirst( lightA, lightB ) {\r\n\r\n\t\treturn ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );\r\n\r\n\t}\r\n\r\n\tfunction WebGLLights() {\r\n\r\n\t\tvar cache = new UniformsCache();\r\n\r\n\t\tvar state = {\r\n\r\n\t\t\tversion: 0,\r\n\r\n\t\t\thash: {\r\n\t\t\t\tdirectionalLength: - 1,\r\n\t\t\t\tpointLength: - 1,\r\n\t\t\t\tspotLength: - 1,\r\n\t\t\t\trectAreaLength: - 1,\r\n\t\t\t\themiLength: - 1,\r\n\r\n\t\t\t\tnumDirectionalShadows: - 1,\r\n\t\t\t\tnumPointShadows: - 1,\r\n\t\t\t\tnumSpotShadows: - 1,\r\n\t\t\t},\r\n\r\n\t\t\tambient: [ 0, 0, 0 ],\r\n\t\t\tprobe: [],\r\n\t\t\tdirectional: [],\r\n\t\t\tdirectionalShadowMap: [],\r\n\t\t\tdirectionalShadowMatrix: [],\r\n\t\t\tspot: [],\r\n\t\t\tspotShadowMap: [],\r\n\t\t\tspotShadowMatrix: [],\r\n\t\t\trectArea: [],\r\n\t\t\tpoint: [],\r\n\t\t\tpointShadowMap: [],\r\n\t\t\tpointShadowMatrix: [],\r\n\t\t\themi: [],\r\n\r\n\t\t\tnumDirectionalShadows: - 1,\r\n\t\t\tnumPointShadows: - 1,\r\n\t\t\tnumSpotShadows: - 1\r\n\r\n\t\t};\r\n\r\n\t\tfor ( var i = 0; i < 9; i ++ ) { state.probe.push( new Vector3() ); }\r\n\r\n\t\tvar vector3 = new Vector3();\r\n\t\tvar matrix4 = new Matrix4();\r\n\t\tvar matrix42 = new Matrix4();\r\n\r\n\t\tfunction setup( lights, shadows, camera ) {\r\n\r\n\t\t\tvar r = 0, g = 0, b = 0;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) { state.probe[ i ].set( 0, 0, 0 ); }\r\n\r\n\t\t\tvar directionalLength = 0;\r\n\t\t\tvar pointLength = 0;\r\n\t\t\tvar spotLength = 0;\r\n\t\t\tvar rectAreaLength = 0;\r\n\t\t\tvar hemiLength = 0;\r\n\r\n\t\t\tvar numDirectionalShadows = 0;\r\n\t\t\tvar numPointShadows = 0;\r\n\t\t\tvar numSpotShadows = 0;\r\n\r\n\t\t\tvar viewMatrix = camera.matrixWorldInverse;\r\n\r\n\t\t\tlights.sort( shadowCastingLightsFirst );\r\n\r\n\t\t\tfor ( var i = 0, l = lights.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar light = lights[ i ];\r\n\r\n\t\t\t\tvar color = light.color;\r\n\t\t\t\tvar intensity = light.intensity;\r\n\t\t\t\tvar distance = light.distance;\r\n\r\n\t\t\t\tvar shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;\r\n\r\n\t\t\t\tif ( light.isAmbientLight ) {\r\n\r\n\t\t\t\t\tr += color.r * intensity;\r\n\t\t\t\t\tg += color.g * intensity;\r\n\t\t\t\t\tb += color.b * intensity;\r\n\r\n\t\t\t\t} else if ( light.isLightProbe ) {\r\n\r\n\t\t\t\t\tfor ( var j = 0; j < 9; j ++ ) {\r\n\r\n\t\t\t\t\t\tstate.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( light.isDirectionalLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.sub( vector3 );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\r\n\t\t\t\t\t\tstate.directionalShadowMap[ directionalLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumDirectionalShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.directional[ directionalLength ] = uniforms;\r\n\r\n\t\t\t\t\tdirectionalLength ++;\r\n\r\n\t\t\t\t} else if ( light.isSpotLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\r\n\t\t\t\t\tuniforms.distance = distance;\r\n\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.sub( vector3 );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.coneCos = Math.cos( light.angle );\r\n\t\t\t\t\tuniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );\r\n\t\t\t\t\tuniforms.decay = light.decay;\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\r\n\t\t\t\t\t\tstate.spotShadowMap[ spotLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.spotShadowMatrix[ spotLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumSpotShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.spot[ spotLength ] = uniforms;\r\n\r\n\t\t\t\t\tspotLength ++;\r\n\r\n\t\t\t\t} else if ( light.isRectAreaLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\t// (a) intensity is the total visible light emitted\r\n\t\t\t\t\t//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );\r\n\r\n\t\t\t\t\t// (b) intensity is the brightness of the light\r\n\t\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\t// extract local rotation of light to derive width/height half vectors\r\n\t\t\t\t\tmatrix42.identity();\r\n\t\t\t\t\tmatrix4.copy( light.matrixWorld );\r\n\t\t\t\t\tmatrix4.premultiply( viewMatrix );\r\n\t\t\t\t\tmatrix42.extractRotation( matrix4 );\r\n\r\n\t\t\t\t\tuniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );\r\n\t\t\t\t\tuniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );\r\n\r\n\t\t\t\t\tuniforms.halfWidth.applyMatrix4( matrix42 );\r\n\t\t\t\t\tuniforms.halfHeight.applyMatrix4( matrix42 );\r\n\r\n\t\t\t\t\t// TODO (abelnation): RectAreaLight distance?\r\n\t\t\t\t\t// uniforms.distance = distance;\r\n\r\n\t\t\t\t\tstate.rectArea[ rectAreaLength ] = uniforms;\r\n\r\n\t\t\t\t\trectAreaLength ++;\r\n\r\n\t\t\t\t} else if ( light.isPointLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\r\n\r\n\t\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\r\n\t\t\t\t\tuniforms.distance = light.distance;\r\n\t\t\t\t\tuniforms.decay = light.decay;\r\n\r\n\t\t\t\t\tuniforms.shadow = light.castShadow;\r\n\r\n\t\t\t\t\tif ( light.castShadow ) {\r\n\r\n\t\t\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\t\t\tuniforms.shadowBias = shadow.bias;\r\n\t\t\t\t\t\tuniforms.shadowRadius = shadow.radius;\r\n\t\t\t\t\t\tuniforms.shadowMapSize = shadow.mapSize;\r\n\t\t\t\t\t\tuniforms.shadowCameraNear = shadow.camera.near;\r\n\t\t\t\t\t\tuniforms.shadowCameraFar = shadow.camera.far;\r\n\r\n\t\t\t\t\t\tstate.pointShadowMap[ pointLength ] = shadowMap;\r\n\t\t\t\t\t\tstate.pointShadowMatrix[ pointLength ] = light.shadow.matrix;\r\n\r\n\t\t\t\t\t\tnumPointShadows ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tstate.point[ pointLength ] = uniforms;\r\n\r\n\t\t\t\t\tpointLength ++;\r\n\r\n\t\t\t\t} else if ( light.isHemisphereLight ) {\r\n\r\n\t\t\t\t\tvar uniforms = cache.get( light );\r\n\r\n\t\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\r\n\t\t\t\t\tuniforms.direction.normalize();\r\n\r\n\t\t\t\t\tuniforms.skyColor.copy( light.color ).multiplyScalar( intensity );\r\n\t\t\t\t\tuniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );\r\n\r\n\t\t\t\t\tstate.hemi[ hemiLength ] = uniforms;\r\n\r\n\t\t\t\t\themiLength ++;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.ambient[ 0 ] = r;\r\n\t\t\tstate.ambient[ 1 ] = g;\r\n\t\t\tstate.ambient[ 2 ] = b;\r\n\r\n\t\t\tvar hash = state.hash;\r\n\r\n\t\t\tif ( hash.directionalLength !== directionalLength ||\r\n\t\t\t\thash.pointLength !== pointLength ||\r\n\t\t\t\thash.spotLength !== spotLength ||\r\n\t\t\t\thash.rectAreaLength !== rectAreaLength ||\r\n\t\t\t\thash.hemiLength !== hemiLength ||\r\n\t\t\t\thash.numDirectionalShadows !== numDirectionalShadows ||\r\n\t\t\t\thash.numPointShadows !== numPointShadows ||\r\n\t\t\t\thash.numSpotShadows !== numSpotShadows ) {\r\n\r\n\t\t\t\tstate.directional.length = directionalLength;\r\n\t\t\t\tstate.spot.length = spotLength;\r\n\t\t\t\tstate.rectArea.length = rectAreaLength;\r\n\t\t\t\tstate.point.length = pointLength;\r\n\t\t\t\tstate.hemi.length = hemiLength;\r\n\r\n\t\t\t\tstate.directionalShadowMap.length = numDirectionalShadows;\r\n\t\t\t\tstate.pointShadowMap.length = numPointShadows;\r\n\t\t\t\tstate.spotShadowMap.length = numSpotShadows;\r\n\t\t\t\tstate.directionalShadowMatrix.length = numDirectionalShadows;\r\n\t\t\t\tstate.pointShadowMatrix.length = numPointShadows;\r\n\t\t\t\tstate.spotShadowMatrix.length = numSpotShadows;\r\n\r\n\t\t\t\thash.directionalLength = directionalLength;\r\n\t\t\t\thash.pointLength = pointLength;\r\n\t\t\t\thash.spotLength = spotLength;\r\n\t\t\t\thash.rectAreaLength = rectAreaLength;\r\n\t\t\t\thash.hemiLength = hemiLength;\r\n\r\n\t\t\t\thash.numDirectionalShadows = numDirectionalShadows;\r\n\t\t\t\thash.numPointShadows = numPointShadows;\r\n\t\t\t\thash.numSpotShadows = numSpotShadows;\r\n\r\n\t\t\t\tstate.version = nextVersion ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tsetup: setup,\r\n\t\t\tstate: state\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WebGLRenderState() {\r\n\r\n\t\tvar lights = new WebGLLights();\r\n\r\n\t\tvar lightsArray = [];\r\n\t\tvar shadowsArray = [];\r\n\r\n\t\tfunction init() {\r\n\r\n\t\t\tlightsArray.length = 0;\r\n\t\t\tshadowsArray.length = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushLight( light ) {\r\n\r\n\t\t\tlightsArray.push( light );\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushShadow( shadowLight ) {\r\n\r\n\t\t\tshadowsArray.push( shadowLight );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setupLights( camera ) {\r\n\r\n\t\t\tlights.setup( lightsArray, shadowsArray, camera );\r\n\r\n\t\t}\r\n\r\n\t\tvar state = {\r\n\t\t\tlightsArray: lightsArray,\r\n\t\t\tshadowsArray: shadowsArray,\r\n\r\n\t\t\tlights: lights\r\n\t\t};\r\n\r\n\t\treturn {\r\n\t\t\tinit: init,\r\n\t\t\tstate: state,\r\n\t\t\tsetupLights: setupLights,\r\n\r\n\t\t\tpushLight: pushLight,\r\n\t\t\tpushShadow: pushShadow\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tfunction WebGLRenderStates() {\r\n\r\n\t\tvar renderStates = new WeakMap();\r\n\r\n\t\tfunction onSceneDispose( event ) {\r\n\r\n\t\t\tvar scene = event.target;\r\n\r\n\t\t\tscene.removeEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\trenderStates.delete( scene );\r\n\r\n\t\t}\r\n\r\n\t\tfunction get( scene, camera ) {\r\n\r\n\t\t\tvar renderState;\r\n\r\n\t\t\tif ( renderStates.has( scene ) === false ) {\r\n\r\n\t\t\t\trenderState = new WebGLRenderState();\r\n\t\t\t\trenderStates.set( scene, new WeakMap() );\r\n\t\t\t\trenderStates.get( scene ).set( camera, renderState );\r\n\r\n\t\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( renderStates.get( scene ).has( camera ) === false ) {\r\n\r\n\t\t\t\t\trenderState = new WebGLRenderState();\r\n\t\t\t\t\trenderStates.get( scene ).set( camera, renderState );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderState = renderStates.get( scene ).get( camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn renderState;\r\n\r\n\t\t}\r\n\r\n\t\tfunction dispose() {\r\n\r\n\t\t\trenderStates = new WeakMap();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tget: get,\r\n\t\t\tdispose: dispose\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author bhouston / https://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshDepthMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshDepthMaterial';\r\n\r\n\t\tthis.depthPacking = BasicDepthPacking;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshDepthMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshDepthMaterial.prototype.constructor = MeshDepthMaterial;\r\n\r\n\tMeshDepthMaterial.prototype.isMeshDepthMaterial = true;\r\n\r\n\tMeshDepthMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.depthPacking = source.depthPacking;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * referencePosition: ,\r\n\t * nearDistance: ,\r\n\t * farDistance: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: \r\n\t *\r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshDistanceMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshDistanceMaterial';\r\n\r\n\t\tthis.referencePosition = new Vector3();\r\n\t\tthis.nearDistance = 1;\r\n\t\tthis.farDistance = 1000;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshDistanceMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;\r\n\r\n\tMeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;\r\n\r\n\tMeshDistanceMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.referencePosition.copy( source.referencePosition );\r\n\t\tthis.nearDistance = source.nearDistance;\r\n\t\tthis.farDistance = source.farDistance;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tvar vsm_frag = \"uniform sampler2D shadow_pass;\\nuniform vec2 resolution;\\nuniform float radius;\\n#include \\nvoid main() {\\n float mean = 0.0;\\n float squared_mean = 0.0;\\n\\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\\n #ifdef HORIZONAL_PASS\\n vec2 distribution = unpack2HalfToRGBA ( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\\n mean += distribution.x;\\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\\n #else\\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\\n mean += depth;\\n squared_mean += depth * depth;\\n #endif\\n }\\n mean = mean * HALF_SAMPLE_RATE;\\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\\n float std_dev = sqrt( squared_mean - mean * mean );\\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\\n}\";\n\n\tvar vsm_vert = \"void main() {\\n\\tgl_Position = vec4( position, 1.0 );\\n}\";\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLShadowMap( _renderer, _objects, maxTextureSize ) {\r\n\r\n\t\tvar _frustum = new Frustum(),\r\n\r\n\t\t\t_shadowMapSize = new Vector2(),\r\n\t\t\t_viewportSize = new Vector2(),\r\n\r\n\t\t\t_viewport = new Vector4(),\r\n\r\n\t\t\t_depthMaterials = [],\r\n\t\t\t_distanceMaterials = [],\r\n\r\n\t\t\t_materialCache = {};\r\n\r\n\t\tvar shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };\r\n\r\n\t\tvar shadowMaterialVertical = new ShaderMaterial( {\r\n\r\n\t\t\tdefines: {\r\n\t\t\t\tSAMPLE_RATE: 2.0 / 8.0,\r\n\t\t\t\tHALF_SAMPLE_RATE: 1.0 / 8.0\r\n\t\t\t},\r\n\r\n\t\t\tuniforms: {\r\n\t\t\t\tshadow_pass: { value: null },\r\n\t\t\t\tresolution: { value: new Vector2() },\r\n\t\t\t\tradius: { value: 4.0 }\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: vsm_vert,\r\n\r\n\t\t\tfragmentShader: vsm_frag\r\n\r\n\t\t} );\r\n\r\n\t\tvar shadowMaterialHorizonal = shadowMaterialVertical.clone();\r\n\t\tshadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;\r\n\r\n\t\tvar fullScreenTri = new BufferGeometry();\r\n\t\tfullScreenTri.setAttribute(\r\n\t\t\t\"position\",\r\n\t\t\tnew BufferAttribute(\r\n\t\t\t\tnew Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),\r\n\t\t\t\t3\r\n\t\t\t)\r\n\t\t);\r\n\r\n\t\tvar fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.autoUpdate = true;\r\n\t\tthis.needsUpdate = false;\r\n\r\n\t\tthis.type = PCFShadowMap;\r\n\r\n\t\tthis.render = function ( lights, scene, camera ) {\r\n\r\n\t\t\tif ( scope.enabled === false ) { return; }\r\n\t\t\tif ( scope.autoUpdate === false && scope.needsUpdate === false ) { return; }\r\n\r\n\t\t\tif ( lights.length === 0 ) { return; }\r\n\r\n\t\t\tvar currentRenderTarget = _renderer.getRenderTarget();\r\n\t\t\tvar activeCubeFace = _renderer.getActiveCubeFace();\r\n\t\t\tvar activeMipmapLevel = _renderer.getActiveMipmapLevel();\r\n\r\n\t\t\tvar _state = _renderer.state;\r\n\r\n\t\t\t// Set GL state for depth map.\r\n\t\t\t_state.setBlending( NoBlending );\r\n\t\t\t_state.buffers.color.setClear( 1, 1, 1, 1 );\r\n\t\t\t_state.buffers.depth.setTest( true );\r\n\t\t\t_state.setScissorTest( false );\r\n\r\n\t\t\t// render depth map\r\n\r\n\t\t\tfor ( var i = 0, il = lights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar light = lights[ i ];\r\n\t\t\t\tvar shadow = light.shadow;\r\n\r\n\t\t\t\tif ( shadow === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );\r\n\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_shadowMapSize.copy( shadow.mapSize );\r\n\r\n\t\t\t\tvar shadowFrameExtents = shadow.getFrameExtents();\r\n\r\n\t\t\t\t_shadowMapSize.multiply( shadowFrameExtents );\r\n\r\n\t\t\t\t_viewportSize.copy( shadow.mapSize );\r\n\r\n\t\t\t\tif ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has shadow exceeding max texture size, reducing' );\r\n\r\n\t\t\t\t\tif ( _shadowMapSize.x > maxTextureSize ) {\r\n\r\n\t\t\t\t\t\t_viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );\r\n\t\t\t\t\t\t_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;\r\n\t\t\t\t\t\tshadow.mapSize.x = _viewportSize.x;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( _shadowMapSize.y > maxTextureSize ) {\r\n\r\n\t\t\t\t\t\t_viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );\r\n\t\t\t\t\t\t_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;\r\n\t\t\t\t\t\tshadow.mapSize.y = _viewportSize.y;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\r\n\r\n\t\t\t\t\tvar pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };\r\n\r\n\t\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\t\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\r\n\r\n\t\t\t\t\tshadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\r\n\t\t\t\t\tshadow.camera.updateProjectionMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( shadow.map === null ) {\r\n\r\n\t\t\t\t\tvar pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };\r\n\r\n\t\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\r\n\t\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\r\n\r\n\t\t\t\t\tshadow.camera.updateProjectionMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_renderer.setRenderTarget( shadow.map );\r\n\t\t\t\t_renderer.clear();\r\n\r\n\t\t\t\tvar viewportCount = shadow.getViewportCount();\r\n\r\n\t\t\t\tfor ( var vp = 0; vp < viewportCount; vp ++ ) {\r\n\r\n\t\t\t\t\tvar viewport = shadow.getViewport( vp );\r\n\r\n\t\t\t\t\t_viewport.set(\r\n\t\t\t\t\t\t_viewportSize.x * viewport.x,\r\n\t\t\t\t\t\t_viewportSize.y * viewport.y,\r\n\t\t\t\t\t\t_viewportSize.x * viewport.z,\r\n\t\t\t\t\t\t_viewportSize.y * viewport.w\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\t_state.viewport( _viewport );\r\n\r\n\t\t\t\t\tshadow.updateMatrices( light, vp );\r\n\r\n\t\t\t\t\t_frustum = shadow.getFrustum();\r\n\r\n\t\t\t\t\trenderObject( scene, camera, shadow.camera, light, this.type );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// do blur pass for VSM\r\n\r\n\t\t\t\tif ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\r\n\r\n\t\t\t\t\tVSMPass( shadow, camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.needsUpdate = false;\r\n\r\n\t\t\t_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\r\n\r\n\t\t};\r\n\r\n\t\tfunction VSMPass( shadow, camera ) {\r\n\r\n\t\t\tvar geometry = _objects.update( fullScreenMesh );\r\n\r\n\t\t\t// vertical pass\r\n\r\n\t\t\tshadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;\r\n\t\t\tshadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;\r\n\t\t\tshadowMaterialVertical.uniforms.radius.value = shadow.radius;\r\n\t\t\t_renderer.setRenderTarget( shadow.mapPass );\r\n\t\t\t_renderer.clear();\r\n\t\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );\r\n\r\n\t\t\t// horizonal pass\r\n\r\n\t\t\tshadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;\r\n\t\t\tshadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;\r\n\t\t\tshadowMaterialHorizonal.uniforms.radius.value = shadow.radius;\r\n\t\t\t_renderer.setRenderTarget( shadow.map );\r\n\t\t\t_renderer.clear();\r\n\t\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {\r\n\r\n\t\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\r\n\r\n\t\t\tvar material = _depthMaterials[ index ];\r\n\r\n\t\t\tif ( material === undefined ) {\r\n\r\n\t\t\t\tmaterial = new MeshDepthMaterial( {\r\n\r\n\t\t\t\t\tdepthPacking: RGBADepthPacking,\r\n\r\n\t\t\t\t\tmorphTargets: useMorphing,\r\n\t\t\t\t\tskinning: useSkinning\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t_depthMaterials[ index ] = material;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {\r\n\r\n\t\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\r\n\r\n\t\t\tvar material = _distanceMaterials[ index ];\r\n\r\n\t\t\tif ( material === undefined ) {\r\n\r\n\t\t\t\tmaterial = new MeshDistanceMaterial( {\r\n\r\n\t\t\t\t\tmorphTargets: useMorphing,\r\n\t\t\t\t\tskinning: useSkinning\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t_distanceMaterials[ index ] = material;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getDepthMaterial( object, material, light, shadowCameraNear, shadowCameraFar, type ) {\r\n\r\n\t\t\tvar geometry = object.geometry;\r\n\r\n\t\t\tvar result = null;\r\n\r\n\t\t\tvar getMaterialVariant = getDepthMaterialVariant;\r\n\t\t\tvar customMaterial = object.customDepthMaterial;\r\n\r\n\t\t\tif ( light.isPointLight === true ) {\r\n\r\n\t\t\t\tgetMaterialVariant = getDistanceMaterialVariant;\r\n\t\t\t\tcustomMaterial = object.customDistanceMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( customMaterial === undefined ) {\r\n\r\n\t\t\t\tvar useMorphing = false;\r\n\r\n\t\t\t\tif ( material.morphTargets === true ) {\r\n\r\n\t\t\t\t\tif ( geometry.isBufferGeometry === true ) {\r\n\r\n\t\t\t\t\t\tuseMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;\r\n\r\n\t\t\t\t\t} else if ( geometry.isGeometry === true ) {\r\n\r\n\t\t\t\t\t\tuseMorphing = geometry.morphTargets && geometry.morphTargets.length > 0;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar useSkinning = false;\r\n\r\n\t\t\t\tif ( object.isSkinnedMesh === true ) {\r\n\r\n\t\t\t\t\tif ( material.skinning === true ) {\r\n\r\n\t\t\t\t\t\tuseSkinning = true;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar useInstancing = object.isInstancedMesh === true;\r\n\r\n\t\t\t\tresult = getMaterialVariant( useMorphing, useSkinning, useInstancing );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresult = customMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _renderer.localClippingEnabled &&\r\n\t\t\t\t\tmaterial.clipShadows === true &&\r\n\t\t\t\t\tmaterial.clippingPlanes.length !== 0 ) {\r\n\r\n\t\t\t\t// in this case we need a unique material instance reflecting the\r\n\t\t\t\t// appropriate state\r\n\r\n\t\t\t\tvar keyA = result.uuid, keyB = material.uuid;\r\n\r\n\t\t\t\tvar materialsForVariant = _materialCache[ keyA ];\r\n\r\n\t\t\t\tif ( materialsForVariant === undefined ) {\r\n\r\n\t\t\t\t\tmaterialsForVariant = {};\r\n\t\t\t\t\t_materialCache[ keyA ] = materialsForVariant;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar cachedMaterial = materialsForVariant[ keyB ];\r\n\r\n\t\t\t\tif ( cachedMaterial === undefined ) {\r\n\r\n\t\t\t\t\tcachedMaterial = result.clone();\r\n\t\t\t\t\tmaterialsForVariant[ keyB ] = cachedMaterial;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tresult = cachedMaterial;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tresult.visible = material.visible;\r\n\t\t\tresult.wireframe = material.wireframe;\r\n\r\n\t\t\tif ( type === VSMShadowMap ) {\r\n\r\n\t\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tresult.clipShadows = material.clipShadows;\r\n\t\t\tresult.clippingPlanes = material.clippingPlanes;\r\n\t\t\tresult.clipIntersection = material.clipIntersection;\r\n\r\n\t\t\tresult.wireframeLinewidth = material.wireframeLinewidth;\r\n\t\t\tresult.linewidth = material.linewidth;\r\n\r\n\t\t\tif ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {\r\n\r\n\t\t\t\tresult.referencePosition.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\t\tresult.nearDistance = shadowCameraNear;\r\n\t\t\t\tresult.farDistance = shadowCameraFar;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObject( object, camera, shadowCamera, light, type ) {\r\n\r\n\t\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\t\tvar visible = object.layers.test( camera.layers );\r\n\r\n\t\t\tif ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {\r\n\r\n\t\t\t\tif ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {\r\n\r\n\t\t\t\t\tobject.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );\r\n\r\n\t\t\t\t\tvar geometry = _objects.update( object );\r\n\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\t\t\t\tfor ( var k = 0, kl = groups.length; k < kl; k ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar group = groups[ k ];\r\n\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\r\n\r\n\t\t\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );\r\n\r\n\t\t\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else if ( material.visible ) {\r\n\r\n\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, material, light, shadowCamera.near, shadowCamera.far, type );\r\n\r\n\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\trenderObject( children[ i ], camera, shadowCamera, light, type );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLState( gl, extensions, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tfunction ColorBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar color = new Vector4();\r\n\t\t\tvar currentColorMask = null;\r\n\t\t\tvar currentColorClear = new Vector4( 0, 0, 0, 0 );\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetMask: function ( colorMask ) {\r\n\r\n\t\t\t\t\tif ( currentColorMask !== colorMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.colorMask( colorMask, colorMask, colorMask, colorMask );\r\n\t\t\t\t\t\tcurrentColorMask = colorMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( r, g, b, a, premultipliedAlpha ) {\r\n\r\n\t\t\t\t\tif ( premultipliedAlpha === true ) {\r\n\r\n\t\t\t\t\t\tr *= a; g *= a; b *= a;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcolor.set( r, g, b, a );\r\n\r\n\t\t\t\t\tif ( currentColorClear.equals( color ) === false ) {\r\n\r\n\t\t\t\t\t\tgl.clearColor( r, g, b, a );\r\n\t\t\t\t\t\tcurrentColorClear.copy( color );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentColorMask = null;\r\n\t\t\t\t\tcurrentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction DepthBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar currentDepthMask = null;\r\n\t\t\tvar currentDepthFunc = null;\r\n\t\t\tvar currentDepthClear = null;\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetTest: function ( depthTest ) {\r\n\r\n\t\t\t\t\tif ( depthTest ) {\r\n\r\n\t\t\t\t\t\tenable( 2929 );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tdisable( 2929 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetMask: function ( depthMask ) {\r\n\r\n\t\t\t\t\tif ( currentDepthMask !== depthMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.depthMask( depthMask );\r\n\t\t\t\t\t\tcurrentDepthMask = depthMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetFunc: function ( depthFunc ) {\r\n\r\n\t\t\t\t\tif ( currentDepthFunc !== depthFunc ) {\r\n\r\n\t\t\t\t\t\tif ( depthFunc ) {\r\n\r\n\t\t\t\t\t\t\tswitch ( depthFunc ) {\r\n\r\n\t\t\t\t\t\t\t\tcase NeverDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 512 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase AlwaysDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 519 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase LessDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 513 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase LessEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase EqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 514 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase GreaterEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 518 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase GreaterDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 516 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase NotEqualDepth:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 517 );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tgl.depthFunc( 515 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tcurrentDepthFunc = depthFunc;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( depth ) {\r\n\r\n\t\t\t\t\tif ( currentDepthClear !== depth ) {\r\n\r\n\t\t\t\t\t\tgl.clearDepth( depth );\r\n\t\t\t\t\t\tcurrentDepthClear = depth;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentDepthMask = null;\r\n\t\t\t\t\tcurrentDepthFunc = null;\r\n\t\t\t\t\tcurrentDepthClear = null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\tfunction StencilBuffer() {\r\n\r\n\t\t\tvar locked = false;\r\n\r\n\t\t\tvar currentStencilMask = null;\r\n\t\t\tvar currentStencilFunc = null;\r\n\t\t\tvar currentStencilRef = null;\r\n\t\t\tvar currentStencilFuncMask = null;\r\n\t\t\tvar currentStencilFail = null;\r\n\t\t\tvar currentStencilZFail = null;\r\n\t\t\tvar currentStencilZPass = null;\r\n\t\t\tvar currentStencilClear = null;\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tsetTest: function ( stencilTest ) {\r\n\r\n\t\t\t\t\tif ( ! locked ) {\r\n\r\n\t\t\t\t\t\tif ( stencilTest ) {\r\n\r\n\t\t\t\t\t\t\tenable( 2960 );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tdisable( 2960 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetMask: function ( stencilMask ) {\r\n\r\n\t\t\t\t\tif ( currentStencilMask !== stencilMask && ! locked ) {\r\n\r\n\t\t\t\t\t\tgl.stencilMask( stencilMask );\r\n\t\t\t\t\t\tcurrentStencilMask = stencilMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetFunc: function ( stencilFunc, stencilRef, stencilMask ) {\r\n\r\n\t\t\t\t\tif ( currentStencilFunc !== stencilFunc ||\r\n\t\t\t\t\t currentStencilRef \t!== stencilRef \t||\r\n\t\t\t\t\t currentStencilFuncMask !== stencilMask ) {\r\n\r\n\t\t\t\t\t\tgl.stencilFunc( stencilFunc, stencilRef, stencilMask );\r\n\r\n\t\t\t\t\t\tcurrentStencilFunc = stencilFunc;\r\n\t\t\t\t\t\tcurrentStencilRef = stencilRef;\r\n\t\t\t\t\t\tcurrentStencilFuncMask = stencilMask;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetOp: function ( stencilFail, stencilZFail, stencilZPass ) {\r\n\r\n\t\t\t\t\tif ( currentStencilFail\t !== stencilFail \t||\r\n\t\t\t\t\t currentStencilZFail !== stencilZFail ||\r\n\t\t\t\t\t currentStencilZPass !== stencilZPass ) {\r\n\r\n\t\t\t\t\t\tgl.stencilOp( stencilFail, stencilZFail, stencilZPass );\r\n\r\n\t\t\t\t\t\tcurrentStencilFail = stencilFail;\r\n\t\t\t\t\t\tcurrentStencilZFail = stencilZFail;\r\n\t\t\t\t\t\tcurrentStencilZPass = stencilZPass;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetLocked: function ( lock ) {\r\n\r\n\t\t\t\t\tlocked = lock;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tsetClear: function ( stencil ) {\r\n\r\n\t\t\t\t\tif ( currentStencilClear !== stencil ) {\r\n\r\n\t\t\t\t\t\tgl.clearStencil( stencil );\r\n\t\t\t\t\t\tcurrentStencilClear = stencil;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\treset: function () {\r\n\r\n\t\t\t\t\tlocked = false;\r\n\r\n\t\t\t\t\tcurrentStencilMask = null;\r\n\t\t\t\t\tcurrentStencilFunc = null;\r\n\t\t\t\t\tcurrentStencilRef = null;\r\n\t\t\t\t\tcurrentStencilFuncMask = null;\r\n\t\t\t\t\tcurrentStencilFail = null;\r\n\t\t\t\t\tcurrentStencilZFail = null;\r\n\t\t\t\t\tcurrentStencilZPass = null;\r\n\t\t\t\t\tcurrentStencilClear = null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar colorBuffer = new ColorBuffer();\r\n\t\tvar depthBuffer = new DepthBuffer();\r\n\t\tvar stencilBuffer = new StencilBuffer();\r\n\r\n\t\tvar maxVertexAttributes = gl.getParameter( 34921 );\r\n\t\tvar newAttributes = new Uint8Array( maxVertexAttributes );\r\n\t\tvar enabledAttributes = new Uint8Array( maxVertexAttributes );\r\n\t\tvar attributeDivisors = new Uint8Array( maxVertexAttributes );\r\n\r\n\t\tvar enabledCapabilities = {};\r\n\r\n\t\tvar currentProgram = null;\r\n\r\n\t\tvar currentBlendingEnabled = null;\r\n\t\tvar currentBlending = null;\r\n\t\tvar currentBlendEquation = null;\r\n\t\tvar currentBlendSrc = null;\r\n\t\tvar currentBlendDst = null;\r\n\t\tvar currentBlendEquationAlpha = null;\r\n\t\tvar currentBlendSrcAlpha = null;\r\n\t\tvar currentBlendDstAlpha = null;\r\n\t\tvar currentPremultipledAlpha = false;\r\n\r\n\t\tvar currentFlipSided = null;\r\n\t\tvar currentCullFace = null;\r\n\r\n\t\tvar currentLineWidth = null;\r\n\r\n\t\tvar currentPolygonOffsetFactor = null;\r\n\t\tvar currentPolygonOffsetUnits = null;\r\n\r\n\t\tvar maxTextures = gl.getParameter( 35661 );\r\n\r\n\t\tvar lineWidthAvailable = false;\r\n\t\tvar version = 0;\r\n\t\tvar glVersion = gl.getParameter( 7938 );\r\n\r\n\t\tif ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {\r\n\r\n\t\t\tversion = parseFloat( /^WebGL\\ ([0-9])/.exec( glVersion )[ 1 ] );\r\n\t\t\tlineWidthAvailable = ( version >= 1.0 );\r\n\r\n\t\t} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {\r\n\r\n\t\t\tversion = parseFloat( /^OpenGL\\ ES\\ ([0-9])/.exec( glVersion )[ 1 ] );\r\n\t\t\tlineWidthAvailable = ( version >= 2.0 );\r\n\r\n\t\t}\r\n\r\n\t\tvar currentTextureSlot = null;\r\n\t\tvar currentBoundTextures = {};\r\n\r\n\t\tvar currentScissor = new Vector4();\r\n\t\tvar currentViewport = new Vector4();\r\n\r\n\t\tfunction createTexture( type, target, count ) {\r\n\r\n\t\t\tvar data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.\r\n\t\t\tvar texture = gl.createTexture();\r\n\r\n\t\t\tgl.bindTexture( type, texture );\r\n\t\t\tgl.texParameteri( type, 10241, 9728 );\r\n\t\t\tgl.texParameteri( type, 10240, 9728 );\r\n\r\n\t\t\tfor ( var i = 0; i < count; i ++ ) {\r\n\r\n\t\t\t\tgl.texImage2D( target + i, 0, 6408, 1, 1, 0, 6408, 5121, data );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t\tvar emptyTextures = {};\r\n\t\temptyTextures[ 3553 ] = createTexture( 3553, 3553, 1 );\r\n\t\temptyTextures[ 34067 ] = createTexture( 34067, 34069, 6 );\r\n\r\n\t\t// init\r\n\r\n\t\tcolorBuffer.setClear( 0, 0, 0, 1 );\r\n\t\tdepthBuffer.setClear( 1 );\r\n\t\tstencilBuffer.setClear( 0 );\r\n\r\n\t\tenable( 2929 );\r\n\t\tdepthBuffer.setFunc( LessEqualDepth );\r\n\r\n\t\tsetFlipSided( false );\r\n\t\tsetCullFace( CullFaceBack );\r\n\t\tenable( 2884 );\r\n\r\n\t\tsetBlending( NoBlending );\r\n\r\n\t\t//\r\n\r\n\t\tfunction initAttributes() {\r\n\r\n\t\t\tfor ( var i = 0, l = newAttributes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tnewAttributes[ i ] = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction enableAttribute( attribute ) {\r\n\r\n\t\t\tenableAttributeAndDivisor( attribute, 0 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction enableAttributeAndDivisor( attribute, meshPerAttribute ) {\r\n\r\n\t\t\tnewAttributes[ attribute ] = 1;\r\n\r\n\t\t\tif ( enabledAttributes[ attribute ] === 0 ) {\r\n\r\n\t\t\t\tgl.enableVertexAttribArray( attribute );\r\n\t\t\t\tenabledAttributes[ attribute ] = 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( attributeDivisors[ attribute ] !== meshPerAttribute ) {\r\n\r\n\t\t\t\tvar extension = isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t\t\textension[ isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );\r\n\t\t\t\tattributeDivisors[ attribute ] = meshPerAttribute;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction disableUnusedAttributes() {\r\n\r\n\t\t\tfor ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {\r\n\r\n\t\t\t\tif ( enabledAttributes[ i ] !== newAttributes[ i ] ) {\r\n\r\n\t\t\t\t\tgl.disableVertexAttribArray( i );\r\n\t\t\t\t\tenabledAttributes[ i ] = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction enable( id ) {\r\n\r\n\t\t\tif ( enabledCapabilities[ id ] !== true ) {\r\n\r\n\t\t\t\tgl.enable( id );\r\n\t\t\t\tenabledCapabilities[ id ] = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction disable( id ) {\r\n\r\n\t\t\tif ( enabledCapabilities[ id ] !== false ) {\r\n\r\n\t\t\t\tgl.disable( id );\r\n\t\t\t\tenabledCapabilities[ id ] = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction useProgram( program ) {\r\n\r\n\t\t\tif ( currentProgram !== program ) {\r\n\r\n\t\t\t\tgl.useProgram( program );\r\n\r\n\t\t\t\tcurrentProgram = program;\r\n\r\n\t\t\t\treturn true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn false;\r\n\r\n\t\t}\r\n\r\n\t\tvar equationToGL = {};\n\t\tequationToGL[ AddEquation ] = 32774;\n\t\tequationToGL[ SubtractEquation ] = 32778;\n\t\tequationToGL[ ReverseSubtractEquation ] = 32779;\r\n\r\n\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\tequationToGL[ MinEquation ] = 32775;\r\n\t\t\tequationToGL[ MaxEquation ] = 32776;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_blend_minmax' );\r\n\r\n\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\tequationToGL[ MinEquation ] = extension.MIN_EXT;\r\n\t\t\t\tequationToGL[ MaxEquation ] = extension.MAX_EXT;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar factorToGL = {};\n\t\tfactorToGL[ ZeroFactor ] = 0;\n\t\tfactorToGL[ OneFactor ] = 1;\n\t\tfactorToGL[ SrcColorFactor ] = 768;\n\t\tfactorToGL[ SrcAlphaFactor ] = 770;\n\t\tfactorToGL[ SrcAlphaSaturateFactor ] = 776;\n\t\tfactorToGL[ DstColorFactor ] = 774;\n\t\tfactorToGL[ DstAlphaFactor ] = 772;\n\t\tfactorToGL[ OneMinusSrcColorFactor ] = 769;\n\t\tfactorToGL[ OneMinusSrcAlphaFactor ] = 771;\n\t\tfactorToGL[ OneMinusDstColorFactor ] = 775;\n\t\tfactorToGL[ OneMinusDstAlphaFactor ] = 773;\r\n\r\n\t\tfunction setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {\r\n\r\n\t\t\tif ( blending === NoBlending ) {\r\n\r\n\t\t\t\tif ( currentBlendingEnabled ) {\r\n\r\n\t\t\t\t\tdisable( 3042 );\r\n\t\t\t\t\tcurrentBlendingEnabled = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! currentBlendingEnabled ) {\r\n\r\n\t\t\t\tenable( 3042 );\r\n\t\t\t\tcurrentBlendingEnabled = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( blending !== CustomBlending ) {\r\n\r\n\t\t\t\tif ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {\r\n\r\n\t\t\t\t\tif ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {\r\n\r\n\t\t\t\t\t\tgl.blendEquation( 32774 );\r\n\r\n\t\t\t\t\t\tcurrentBlendEquation = AddEquation;\r\n\t\t\t\t\t\tcurrentBlendEquationAlpha = AddEquation;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( premultipliedAlpha ) {\r\n\r\n\t\t\t\t\t\tswitch ( blending ) {\r\n\r\n\t\t\t\t\t\t\tcase NormalBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 1, 771, 1, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase AdditiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 1, 1 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase SubtractiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 0, 0, 769, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase MultiplyBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 0, 768, 0, 770 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tswitch ( blending ) {\r\n\r\n\t\t\t\t\t\t\tcase NormalBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFuncSeparate( 770, 771, 1, 771 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase AdditiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 770, 1 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase SubtractiveBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 0, 769 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tcase MultiplyBlending:\r\n\t\t\t\t\t\t\t\tgl.blendFunc( 0, 768 );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcurrentBlendSrc = null;\r\n\t\t\t\t\tcurrentBlendDst = null;\r\n\t\t\t\t\tcurrentBlendSrcAlpha = null;\r\n\t\t\t\t\tcurrentBlendDstAlpha = null;\r\n\r\n\t\t\t\t\tcurrentBlending = blending;\r\n\t\t\t\t\tcurrentPremultipledAlpha = premultipliedAlpha;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// custom blending\r\n\r\n\t\t\tblendEquationAlpha = blendEquationAlpha || blendEquation;\r\n\t\t\tblendSrcAlpha = blendSrcAlpha || blendSrc;\r\n\t\t\tblendDstAlpha = blendDstAlpha || blendDst;\r\n\r\n\t\t\tif ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {\r\n\r\n\t\t\t\tgl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );\r\n\r\n\t\t\t\tcurrentBlendEquation = blendEquation;\r\n\t\t\t\tcurrentBlendEquationAlpha = blendEquationAlpha;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {\r\n\r\n\t\t\t\tgl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );\r\n\r\n\t\t\t\tcurrentBlendSrc = blendSrc;\r\n\t\t\t\tcurrentBlendDst = blendDst;\r\n\t\t\t\tcurrentBlendSrcAlpha = blendSrcAlpha;\r\n\t\t\t\tcurrentBlendDstAlpha = blendDstAlpha;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcurrentBlending = blending;\r\n\t\t\tcurrentPremultipledAlpha = null;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setMaterial( material, frontFaceCW ) {\r\n\r\n\t\t\tmaterial.side === DoubleSide\r\n\t\t\t\t? disable( 2884 )\r\n\t\t\t\t: enable( 2884 );\r\n\r\n\t\t\tvar flipSided = ( material.side === BackSide );\r\n\t\t\tif ( frontFaceCW ) { flipSided = ! flipSided; }\r\n\r\n\t\t\tsetFlipSided( flipSided );\r\n\r\n\t\t\t( material.blending === NormalBlending && material.transparent === false )\r\n\t\t\t\t? setBlending( NoBlending )\r\n\t\t\t\t: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );\r\n\r\n\t\t\tdepthBuffer.setFunc( material.depthFunc );\r\n\t\t\tdepthBuffer.setTest( material.depthTest );\r\n\t\t\tdepthBuffer.setMask( material.depthWrite );\r\n\t\t\tcolorBuffer.setMask( material.colorWrite );\r\n\r\n\t\t\tvar stencilWrite = material.stencilWrite;\r\n\t\t\tstencilBuffer.setTest( stencilWrite );\r\n\t\t\tif ( stencilWrite ) {\r\n\r\n\t\t\t\tstencilBuffer.setMask( material.stencilWriteMask );\r\n\t\t\t\tstencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );\r\n\t\t\t\tstencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction setFlipSided( flipSided ) {\r\n\r\n\t\t\tif ( currentFlipSided !== flipSided ) {\r\n\r\n\t\t\t\tif ( flipSided ) {\r\n\r\n\t\t\t\t\tgl.frontFace( 2304 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tgl.frontFace( 2305 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcurrentFlipSided = flipSided;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setCullFace( cullFace ) {\r\n\r\n\t\t\tif ( cullFace !== CullFaceNone ) {\r\n\r\n\t\t\t\tenable( 2884 );\r\n\r\n\t\t\t\tif ( cullFace !== currentCullFace ) {\r\n\r\n\t\t\t\t\tif ( cullFace === CullFaceBack ) {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1029 );\r\n\r\n\t\t\t\t\t} else if ( cullFace === CullFaceFront ) {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1028 );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tgl.cullFace( 1032 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 2884 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcurrentCullFace = cullFace;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setLineWidth( width ) {\r\n\r\n\t\t\tif ( width !== currentLineWidth ) {\r\n\r\n\t\t\t\tif ( lineWidthAvailable ) { gl.lineWidth( width ); }\r\n\r\n\t\t\t\tcurrentLineWidth = width;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setPolygonOffset( polygonOffset, factor, units ) {\r\n\r\n\t\t\tif ( polygonOffset ) {\r\n\r\n\t\t\t\tenable( 32823 );\r\n\r\n\t\t\t\tif ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {\r\n\r\n\t\t\t\t\tgl.polygonOffset( factor, units );\r\n\r\n\t\t\t\t\tcurrentPolygonOffsetFactor = factor;\r\n\t\t\t\t\tcurrentPolygonOffsetUnits = units;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 32823 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setScissorTest( scissorTest ) {\r\n\r\n\t\t\tif ( scissorTest ) {\r\n\r\n\t\t\t\tenable( 3089 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdisable( 3089 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// texture\r\n\r\n\t\tfunction activeTexture( webglSlot ) {\r\n\r\n\t\t\tif ( webglSlot === undefined ) { webglSlot = 33984 + maxTextures - 1; }\r\n\r\n\t\t\tif ( currentTextureSlot !== webglSlot ) {\r\n\r\n\t\t\t\tgl.activeTexture( webglSlot );\r\n\t\t\t\tcurrentTextureSlot = webglSlot;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction bindTexture( webglType, webglTexture ) {\r\n\r\n\t\t\tif ( currentTextureSlot === null ) {\r\n\r\n\t\t\t\tactiveTexture();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\r\n\r\n\t\t\tif ( boundTexture === undefined ) {\r\n\r\n\t\t\t\tboundTexture = { type: undefined, texture: undefined };\r\n\t\t\t\tcurrentBoundTextures[ currentTextureSlot ] = boundTexture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {\r\n\r\n\t\t\t\tgl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );\r\n\r\n\t\t\t\tboundTexture.type = webglType;\r\n\t\t\t\tboundTexture.texture = webglTexture;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction unbindTexture() {\r\n\r\n\t\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\r\n\r\n\t\t\tif ( boundTexture !== undefined && boundTexture.type !== undefined ) {\r\n\r\n\t\t\t\tgl.bindTexture( boundTexture.type, null );\r\n\r\n\t\t\t\tboundTexture.type = undefined;\r\n\t\t\t\tboundTexture.texture = undefined;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction compressedTexImage2D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.compressedTexImage2D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction texImage2D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.texImage2D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction texImage3D() {\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\tgl.texImage3D.apply( gl, arguments );\r\n\r\n\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLState:', error );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction scissor( scissor ) {\r\n\r\n\t\t\tif ( currentScissor.equals( scissor ) === false ) {\r\n\r\n\t\t\t\tgl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );\r\n\t\t\t\tcurrentScissor.copy( scissor );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction viewport( viewport ) {\r\n\r\n\t\t\tif ( currentViewport.equals( viewport ) === false ) {\r\n\r\n\t\t\t\tgl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );\r\n\t\t\t\tcurrentViewport.copy( viewport );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction reset() {\r\n\r\n\t\t\tfor ( var i = 0; i < enabledAttributes.length; i ++ ) {\r\n\r\n\t\t\t\tif ( enabledAttributes[ i ] === 1 ) {\r\n\r\n\t\t\t\t\tgl.disableVertexAttribArray( i );\r\n\t\t\t\t\tenabledAttributes[ i ] = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tenabledCapabilities = {};\r\n\r\n\t\t\tcurrentTextureSlot = null;\r\n\t\t\tcurrentBoundTextures = {};\r\n\r\n\t\t\tcurrentProgram = null;\r\n\r\n\t\t\tcurrentBlending = null;\r\n\r\n\t\t\tcurrentFlipSided = null;\r\n\t\t\tcurrentCullFace = null;\r\n\r\n\t\t\tcolorBuffer.reset();\r\n\t\t\tdepthBuffer.reset();\r\n\t\t\tstencilBuffer.reset();\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tbuffers: {\r\n\t\t\t\tcolor: colorBuffer,\r\n\t\t\t\tdepth: depthBuffer,\r\n\t\t\t\tstencil: stencilBuffer\r\n\t\t\t},\r\n\r\n\t\t\tinitAttributes: initAttributes,\r\n\t\t\tenableAttribute: enableAttribute,\r\n\t\t\tenableAttributeAndDivisor: enableAttributeAndDivisor,\r\n\t\t\tdisableUnusedAttributes: disableUnusedAttributes,\r\n\t\t\tenable: enable,\r\n\t\t\tdisable: disable,\r\n\r\n\t\t\tuseProgram: useProgram,\r\n\r\n\t\t\tsetBlending: setBlending,\r\n\t\t\tsetMaterial: setMaterial,\r\n\r\n\t\t\tsetFlipSided: setFlipSided,\r\n\t\t\tsetCullFace: setCullFace,\r\n\r\n\t\t\tsetLineWidth: setLineWidth,\r\n\t\t\tsetPolygonOffset: setPolygonOffset,\r\n\r\n\t\t\tsetScissorTest: setScissorTest,\r\n\r\n\t\t\tactiveTexture: activeTexture,\r\n\t\t\tbindTexture: bindTexture,\r\n\t\t\tunbindTexture: unbindTexture,\r\n\t\t\tcompressedTexImage2D: compressedTexImage2D,\r\n\t\t\ttexImage2D: texImage2D,\r\n\t\t\ttexImage3D: texImage3D,\r\n\r\n\t\t\tscissor: scissor,\r\n\t\t\tviewport: viewport,\r\n\r\n\t\t\treset: reset\r\n\r\n\t\t};\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\t\tvar maxTextures = capabilities.maxTextures;\r\n\t\tvar maxCubemapSize = capabilities.maxCubemapSize;\r\n\t\tvar maxTextureSize = capabilities.maxTextureSize;\r\n\t\tvar maxSamples = capabilities.maxSamples;\r\n\r\n\t\tvar _videoTextures = new WeakMap();\r\n\t\tvar _canvas;\r\n\r\n\t\t// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,\r\n\t\t// also OffscreenCanvas.getContext(\"webgl\"), but not OffscreenCanvas.getContext(\"2d\")!\r\n\t\t// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).\r\n\r\n\t\tvar useOffscreenCanvas = false;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tuseOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'\r\n\t\t\t\t&& ( new OffscreenCanvas( 1, 1 ).getContext( \"2d\" ) ) !== null;\r\n\r\n\t\t} catch ( err ) {\r\n\r\n\t\t\t// Ignore any errors\r\n\r\n\t\t}\r\n\r\n\t\tfunction createCanvas( width, height ) {\r\n\r\n\t\t\t// Use OffscreenCanvas when available. Specially needed in web workers\r\n\r\n\t\t\treturn useOffscreenCanvas ?\r\n\t\t\t\tnew OffscreenCanvas( width, height ) :\r\n\t\t\t\tdocument.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\r\n\r\n\t\t}\r\n\r\n\t\tfunction resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {\r\n\r\n\t\t\tvar scale = 1;\r\n\r\n\t\t\t// handle case if texture exceeds max size\r\n\r\n\t\t\tif ( image.width > maxSize || image.height > maxSize ) {\r\n\r\n\t\t\t\tscale = maxSize / Math.max( image.width, image.height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// only perform resize if necessary\r\n\r\n\t\t\tif ( scale < 1 || needsPowerOfTwo === true ) {\r\n\r\n\t\t\t\t// only perform resize for certain image types\r\n\r\n\t\t\t\tif ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||\r\n\t\t\t\t\t( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||\r\n\t\t\t\t\t( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {\r\n\r\n\t\t\t\t\tvar floor = needsPowerOfTwo ? _Math.floorPowerOfTwo : Math.floor;\r\n\r\n\t\t\t\t\tvar width = floor( scale * image.width );\r\n\t\t\t\t\tvar height = floor( scale * image.height );\r\n\r\n\t\t\t\t\tif ( _canvas === undefined ) { _canvas = createCanvas( width, height ); }\r\n\r\n\t\t\t\t\t// cube textures can't reuse the same canvas\r\n\r\n\t\t\t\t\tvar canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;\r\n\r\n\t\t\t\t\tcanvas.width = width;\r\n\t\t\t\t\tcanvas.height = height;\r\n\r\n\t\t\t\t\tvar context = canvas.getContext( '2d' );\r\n\t\t\t\t\tcontext.drawImage( image, 0, 0, width, height );\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );\r\n\r\n\t\t\t\t\treturn canvas;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tif ( 'data' in image ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn image;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn image;\r\n\r\n\t\t}\r\n\r\n\t\tfunction isPowerOfTwo( image ) {\r\n\r\n\t\t\treturn _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height );\r\n\r\n\t\t}\r\n\r\n\t\tfunction textureNeedsPowerOfTwo( texture ) {\r\n\r\n\t\t\tif ( isWebGL2 ) { return false; }\r\n\r\n\t\t\treturn ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||\r\n\t\t\t\t( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );\r\n\r\n\t\t}\r\n\r\n\t\tfunction textureNeedsGenerateMipmaps( texture, supportsMips ) {\r\n\r\n\t\t\treturn texture.generateMipmaps && supportsMips &&\r\n\t\t\t\ttexture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateMipmap( target, texture, width, height ) {\r\n\r\n\t\t\t_gl.generateMipmap( target );\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\t// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11\r\n\t\t\ttextureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getInternalFormat( glFormat, glType ) {\r\n\r\n\t\t\tif ( isWebGL2 === false ) { return glFormat; }\r\n\r\n\t\t\tvar internalFormat = glFormat;\r\n\r\n\t\t\tif ( glFormat === 6403 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 33326; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 33325; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 33321; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( glFormat === 6407 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 34837; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 34843; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 32849; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( glFormat === 6408 ) {\r\n\r\n\t\t\t\tif ( glType === 5126 ) { internalFormat = 34836; }\r\n\t\t\t\tif ( glType === 5131 ) { internalFormat = 34842; }\r\n\t\t\t\tif ( glType === 5121 ) { internalFormat = 32856; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( internalFormat === 33325 || internalFormat === 33326 ||\r\n\t\t\t\tinternalFormat === 34842 || internalFormat === 34836 ) {\r\n\r\n\t\t\t\textensions.get( 'EXT_color_buffer_float' );\r\n\r\n\t\t\t} else if ( internalFormat === 34843 || internalFormat === 34837 ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Floating point textures with RGB format not supported. Please use RGBA instead.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn internalFormat;\r\n\r\n\t\t}\r\n\r\n\t\t// Fallback filters for non-power-of-2 textures\r\n\r\n\t\tfunction filterFallback( f ) {\r\n\r\n\t\t\tif ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {\r\n\r\n\t\t\t\treturn 9728;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn 9729;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction onTextureDispose( event ) {\r\n\r\n\t\t\tvar texture = event.target;\r\n\r\n\t\t\ttexture.removeEventListener( 'dispose', onTextureDispose );\r\n\r\n\t\t\tdeallocateTexture( texture );\r\n\r\n\t\t\tif ( texture.isVideoTexture ) {\r\n\r\n\t\t\t\t_videoTextures.delete( texture );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tinfo.memory.textures --;\r\n\r\n\t\t}\r\n\r\n\t\tfunction onRenderTargetDispose( event ) {\r\n\r\n\t\t\tvar renderTarget = event.target;\r\n\r\n\t\t\trenderTarget.removeEventListener( 'dispose', onRenderTargetDispose );\r\n\r\n\t\t\tdeallocateRenderTarget( renderTarget );\r\n\r\n\t\t\tinfo.memory.textures --;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction deallocateTexture( texture ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( textureProperties.__webglInit === undefined ) { return; }\r\n\r\n\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\r\n\r\n\t\t\tproperties.remove( texture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction deallocateRenderTarget( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\r\n\t\t\tif ( ! renderTarget ) { return; }\r\n\r\n\t\t\tif ( textureProperties.__webglTexture !== undefined ) {\r\n\r\n\t\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.depthTexture ) {\r\n\r\n\t\t\t\trenderTarget.depthTexture.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );\r\n\t\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );\r\n\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) { _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( renderTarget.isWebGLMultiviewRenderTarget ) {\r\n\r\n\t\t\t\t_gl.deleteTexture( renderTargetProperties.__webglColorTexture );\r\n\t\t\t\t_gl.deleteTexture( renderTargetProperties.__webglDepthStencilTexture );\r\n\r\n\t\t\t\tinfo.memory.textures -= 2;\r\n\r\n\t\t\t\tfor ( var i = 0, il = renderTargetProperties.__webglViewFramebuffers.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglViewFramebuffers[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tproperties.remove( renderTarget.texture );\r\n\t\t\tproperties.remove( renderTarget );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar textureUnits = 0;\r\n\r\n\t\tfunction resetTextureUnits() {\r\n\r\n\t\t\ttextureUnits = 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction allocateTextureUnit() {\r\n\r\n\t\t\tvar textureUnit = textureUnits;\r\n\r\n\t\t\tif ( textureUnit >= maxTextures ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttextureUnits += 1;\r\n\r\n\t\t\treturn textureUnit;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction setTexture2D( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.isVideoTexture ) { updateVideoTexture( texture ); }\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tvar image = texture.image;\r\n\r\n\t\t\t\tif ( image === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );\r\n\r\n\t\t\t\t} else if ( image.complete === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 3553, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTexture2DArray( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 35866, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTexture3D( texture, slot ) {\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 32879, textureProperties.__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTextureCube( texture, slot ) {\r\n\r\n\t\t\tif ( texture.image.length !== 6 ) { return; }\r\n\r\n\t\t\tvar textureProperties = properties.get( texture );\r\n\r\n\t\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\r\n\r\n\t\t\t\tinitTexture( textureProperties, texture );\r\n\r\n\t\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\r\n\t\t\t\t_gl.pixelStorei( 37440, texture.flipY );\r\n\r\n\t\t\t\tvar isCompressed = ( texture && texture.isCompressedTexture );\r\n\t\t\t\tvar isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );\r\n\r\n\t\t\t\tvar cubeImage = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\tif ( ! isCompressed && ! isDataTexture ) {\r\n\r\n\t\t\t\t\t\tcubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tcubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar image = cubeImage[ 0 ],\r\n\t\t\t\t\tsupportsMips = isPowerOfTwo( image ) || isWebGL2,\r\n\t\t\t\t\tglFormat = utils.convert( texture.format ),\r\n\t\t\t\t\tglType = utils.convert( texture.type ),\r\n\t\t\t\t\tglInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\t\tsetTextureParameters( 34067, texture, supportsMips );\r\n\r\n\t\t\t\tvar mipmaps;\r\n\r\n\t\t\t\tif ( isCompressed ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmaps = cubeImage[ i ].mipmaps;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( glFormat !== null ) {\r\n\r\n\t\t\t\t\t\t\t\t\tstate.compressedTexImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\r\n\r\n\t\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tmipmaps = texture.mipmaps;\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\tif ( isDataTexture ) {\r\n\r\n\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\t\t\t\t\t\t\t\tvar mipmapImage = mipmap.image[ i ].image;\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\r\n\r\n\t\t\t\t\t\t\t\tstate.texImage2D( 34069 + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\t// We assume images for cube map have the same size.\r\n\t\t\t\t\tgenerateMipmap( 34067, texture, image.width, image.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextureProperties.__version = texture.version;\r\n\r\n\t\t\t\tif ( texture.onUpdate ) { texture.onUpdate( texture ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction setTextureCubeDynamic( texture, slot ) {\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( 34067, properties.get( texture ).__webglTexture );\r\n\r\n\t\t}\r\n\r\n\t\tvar wrappingToGL = {};\n\t\twrappingToGL[ RepeatWrapping ] = 10497;\n\t\twrappingToGL[ ClampToEdgeWrapping ] = 33071;\n\t\twrappingToGL[ MirroredRepeatWrapping ] = 33648;\r\n\r\n\t\tvar filterToGL = {};\n\t\tfilterToGL[ NearestFilter ] = 9728;\n\t\tfilterToGL[ NearestMipmapNearestFilter ] = 9984;\n\t\tfilterToGL[ NearestMipmapLinearFilter ] = 9986;\n\t\tfilterToGL[ LinearFilter ] = 9729;\n\t\tfilterToGL[ LinearMipmapNearestFilter ] = 9985;\n\t\tfilterToGL[ LinearMipmapLinearFilter ] = 9987;\r\n\r\n\t\tfunction setTextureParameters( textureType, texture, supportsMips ) {\r\n\r\n\t\t\tif ( supportsMips ) {\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10242, wrappingToGL[ texture.wrapS ] );\r\n\t\t\t\t_gl.texParameteri( textureType, 10243, wrappingToGL[ texture.wrapT ] );\r\n\r\n\t\t\t\tif ( textureType === 32879 || textureType === 35866 ) {\r\n\r\n\t\t\t\t\t_gl.texParameteri( textureType, 32882, wrappingToGL[ texture.wrapR ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10240, filterToGL[ texture.magFilter ] );\r\n\t\t\t\t_gl.texParameteri( textureType, 10241, filterToGL[ texture.minFilter ] );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10242, 33071 );\r\n\t\t\t\t_gl.texParameteri( textureType, 10243, 33071 );\r\n\r\n\t\t\t\tif ( textureType === 32879 || textureType === 35866 ) {\r\n\r\n\t\t\t\t\t_gl.texParameteri( textureType, 32882, 33071 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.texParameteri( textureType, 10240, filterFallback( texture.magFilter ) );\r\n\t\t\t\t_gl.texParameteri( textureType, 10241, filterFallback( texture.minFilter ) );\r\n\r\n\t\t\t\tif ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\r\n\r\n\t\t\tif ( extension ) {\r\n\r\n\t\t\t\tif ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) { return; }\r\n\t\t\t\tif ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) { return; }\r\n\r\n\t\t\t\tif ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {\r\n\r\n\t\t\t\t\t_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );\r\n\t\t\t\t\tproperties.get( texture ).__currentAnisotropy = texture.anisotropy;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction initTexture( textureProperties, texture ) {\r\n\r\n\t\t\tif ( textureProperties.__webglInit === undefined ) {\r\n\r\n\t\t\t\ttextureProperties.__webglInit = true;\r\n\r\n\t\t\t\ttexture.addEventListener( 'dispose', onTextureDispose );\r\n\r\n\t\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\r\n\r\n\t\t\t\tinfo.memory.textures ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction uploadTexture( textureProperties, texture, slot ) {\r\n\r\n\t\t\tvar textureType = 3553;\r\n\r\n\t\t\tif ( texture.isDataTexture2DArray ) { textureType = 35866; }\r\n\t\t\tif ( texture.isDataTexture3D ) { textureType = 32879; }\r\n\r\n\t\t\tinitTexture( textureProperties, texture );\r\n\r\n\t\t\tstate.activeTexture( 33984 + slot );\r\n\t\t\tstate.bindTexture( textureType, textureProperties.__webglTexture );\r\n\r\n\t\t\t_gl.pixelStorei( 37440, texture.flipY );\r\n\t\t\t_gl.pixelStorei( 37441, texture.premultiplyAlpha );\r\n\t\t\t_gl.pixelStorei( 3317, texture.unpackAlignment );\r\n\r\n\t\t\tvar needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;\r\n\t\t\tvar image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );\r\n\r\n\t\t\tvar supportsMips = isPowerOfTwo( image ) || isWebGL2,\r\n\t\t\t\tglFormat = utils.convert( texture.format ),\r\n\t\t\t\tglType = utils.convert( texture.type ),\r\n\t\t\t\tglInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\tsetTextureParameters( textureType, texture, supportsMips );\r\n\r\n\t\t\tvar mipmap, mipmaps = texture.mipmaps;\r\n\r\n\t\t\tif ( texture.isDepthTexture ) {\r\n\r\n\t\t\t\t// populate depth texture with dummy data\r\n\r\n\t\t\t\tglInternalFormat = 6402;\r\n\r\n\t\t\t\tif ( texture.type === FloatType ) {\r\n\r\n\t\t\t\t\tif ( isWebGL2 === false ) { throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); }\r\n\t\t\t\t\tglInternalFormat = 36012;\r\n\r\n\t\t\t\t} else if ( isWebGL2 ) {\r\n\r\n\t\t\t\t\t// WebGL 2.0 requires signed internalformat for glTexImage2D\r\n\t\t\t\t\tglInternalFormat = 33189;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texture.format === DepthFormat && glInternalFormat === 6402 ) {\r\n\r\n\t\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\r\n\t\t\t\t\t// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT\r\n\t\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\t\tif ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );\r\n\r\n\t\t\t\t\t\ttexture.type = UnsignedShortType;\r\n\t\t\t\t\t\tglType = utils.convert( texture.type );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Depth stencil textures need the DEPTH_STENCIL internal format\r\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\tif ( texture.format === DepthStencilFormat ) {\r\n\r\n\t\t\t\t\tglInternalFormat = 34041;\r\n\r\n\t\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\r\n\t\t\t\t\t// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.\r\n\t\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\r\n\t\t\t\t\tif ( texture.type !== UnsignedInt248Type ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );\r\n\r\n\t\t\t\t\t\ttexture.type = UnsignedInt248Type;\r\n\t\t\t\t\t\tglType = utils.convert( texture.type );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );\r\n\r\n\t\t\t} else if ( texture.isDataTexture ) {\r\n\r\n\t\t\t\t// use manually created mipmaps if available\r\n\t\t\t\t// if there are no manual mipmaps\r\n\t\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\r\n\r\n\t\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.generateMipmaps = false;\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( texture.isCompressedTexture ) {\r\n\r\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\r\n\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\r\n\r\n\t\t\t\t\t\tif ( glFormat !== null ) {\r\n\r\n\t\t\t\t\t\t\tstate.compressedTexImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t} else if ( texture.isDataTexture2DArray ) {\r\n\r\n\t\t\t\tstate.texImage3D( 35866, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\r\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t} else if ( texture.isDataTexture3D ) {\r\n\r\n\t\t\t\tstate.texImage3D( 32879, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\r\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// regular Texture (image, video, canvas)\r\n\r\n\t\t\t\t// use manually created mipmaps if available\r\n\t\t\t\t// if there are no manual mipmaps\r\n\t\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\r\n\r\n\t\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tmipmap = mipmaps[ i ];\r\n\t\t\t\t\t\tstate.texImage2D( 3553, i, glInternalFormat, glFormat, glType, mipmap );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.generateMipmaps = false;\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstate.texImage2D( 3553, 0, glInternalFormat, glFormat, glType, image );\r\n\t\t\t\t\ttextureProperties.__maxMipLevel = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\tgenerateMipmap( 3553, texture, image.width, image.height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttextureProperties.__version = texture.version;\r\n\r\n\t\t\tif ( texture.onUpdate ) { texture.onUpdate( texture ); }\r\n\r\n\t\t}\r\n\r\n\t\t// Render targets\r\n\r\n\t\t// Setup storage for target texture and bind it to correct framebuffer\r\n\t\tfunction setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {\r\n\r\n\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\t\t\tstate.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );\r\n\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\t\t\t_gl.framebufferTexture2D( 36160, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );\r\n\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Setup storage for internal depth/stencil buffers and bind to correct framebuffer\r\n\t\tfunction setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {\r\n\r\n\t\t\t_gl.bindRenderbuffer( 36161, renderbuffer );\r\n\r\n\t\t\tif ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, 33189, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, 33189, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_gl.framebufferRenderbuffer( 36160, 36096, 36161, renderbuffer );\r\n\r\n\t\t\t} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, 35056, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, 34041, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\t_gl.framebufferRenderbuffer( 36160, 33306, 36161, renderbuffer );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\r\n\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.renderbufferStorage( 36161, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_gl.bindRenderbuffer( 36161, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Setup resources for a Depth Texture for a FBO (needs an extension)\r\n\t\tfunction setupDepthTexture( framebuffer, renderTarget ) {\r\n\r\n\t\t\tvar isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube );\r\n\t\t\tif ( isCube ) { throw new Error( 'Depth Texture with cube render targets is not supported' ); }\r\n\r\n\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\r\n\t\t\tif ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {\r\n\r\n\t\t\t\tthrow new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// upload an empty depth texture with framebuffer size\r\n\t\t\tif ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||\r\n\t\t\t\t\trenderTarget.depthTexture.image.width !== renderTarget.width ||\r\n\t\t\t\t\trenderTarget.depthTexture.image.height !== renderTarget.height ) {\r\n\r\n\t\t\t\trenderTarget.depthTexture.image.width = renderTarget.width;\r\n\t\t\t\trenderTarget.depthTexture.image.height = renderTarget.height;\r\n\t\t\t\trenderTarget.depthTexture.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetTexture2D( renderTarget.depthTexture, 0 );\r\n\r\n\t\t\tvar webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;\r\n\r\n\t\t\tif ( renderTarget.depthTexture.format === DepthFormat ) {\r\n\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 36096, 3553, webglDepthTexture, 0 );\r\n\r\n\t\t\t} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {\r\n\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 33306, 3553, webglDepthTexture, 0 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthrow new Error( 'Unknown depthTexture format' );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Setup GL resources for a non-texture depth buffer\r\n\t\tfunction setupDepthRenderbuffer( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\r\n\t\t\tvar isCube = ( renderTarget.isWebGLRenderTargetCube === true );\r\n\r\n\t\t\tif ( renderTarget.depthTexture ) {\r\n\r\n\t\t\t\tif ( isCube ) { throw new Error( 'target.depthTexture not supported in Cube render targets' ); }\r\n\r\n\t\t\t\tsetupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer[ i ] );\r\n\t\t\t\t\t\trenderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();\r\n\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );\r\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();\r\n\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\t\t}\r\n\r\n\t\t// Set up GL resources for the render target\r\n\t\tfunction setupRenderTarget( renderTarget ) {\r\n\r\n\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\r\n\t\t\trenderTarget.addEventListener( 'dispose', onRenderTargetDispose );\r\n\r\n\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\r\n\r\n\t\t\tinfo.memory.textures ++;\r\n\r\n\t\t\tvar isCube = ( renderTarget.isWebGLRenderTargetCube === true );\r\n\t\t\tvar isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );\r\n\t\t\tvar isMultiview = ( renderTarget.isWebGLMultiviewRenderTarget === true );\r\n\t\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\r\n\r\n\t\t\t// Setup framebuffer\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\trenderTargetProperties.__webglFramebuffer = [];\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();\r\n\r\n\t\t\t\tif ( isMultisample ) {\r\n\r\n\t\t\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\t\t\trenderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();\r\n\t\t\t\t\t\trenderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();\r\n\r\n\t\t\t\t\t\t_gl.bindRenderbuffer( 36161, renderTargetProperties.__webglColorRenderbuffer );\r\n\t\t\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\r\n\t\t\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\r\n\t\t\t\t\t\tvar glInternalFormat = getInternalFormat( glFormat, glType );\r\n\t\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\r\n\t\t\t\t\t\t_gl.renderbufferStorageMultisample( 36161, samples, glInternalFormat, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglMultisampledFramebuffer );\r\n\t\t\t\t\t\t_gl.framebufferRenderbuffer( 36160, 36064, 36161, renderTargetProperties.__webglColorRenderbuffer );\r\n\t\t\t\t\t\t_gl.bindRenderbuffer( 36161, null );\r\n\r\n\t\t\t\t\t\tif ( renderTarget.depthBuffer ) {\r\n\r\n\t\t\t\t\t\t\trenderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();\r\n\t\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( isMultiview ) {\r\n\r\n\t\t\t\t\tvar width = renderTarget.width;\r\n\t\t\t\t\tvar height = renderTarget.height;\r\n\t\t\t\t\tvar numViews = renderTarget.numViews;\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, renderTargetProperties.__webglFramebuffer );\r\n\r\n\t\t\t\t\tvar ext = extensions.get( 'OVR_multiview2' );\r\n\r\n\t\t\t\t\tinfo.memory.textures += 2;\r\n\r\n\t\t\t\t\tvar colorTexture = _gl.createTexture();\r\n\t\t\t\t\t_gl.bindTexture( 35866, colorTexture );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10240, 9728 );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10241, 9728 );\r\n\t\t\t\t\t_gl.texImage3D( 35866, 0, 32856, width, height, numViews, 0, 6408, 5121, null );\r\n\t\t\t\t\text.framebufferTextureMultiviewOVR( 36160, 36064, colorTexture, 0, 0, numViews );\r\n\r\n\t\t\t\t\tvar depthStencilTexture = _gl.createTexture();\r\n\t\t\t\t\t_gl.bindTexture( 35866, depthStencilTexture );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10240, 9728 );\r\n\t\t\t\t\t_gl.texParameteri( 35866, 10241, 9728 );\r\n\t\t\t\t\t_gl.texImage3D( 35866, 0, 35056, width, height, numViews, 0, 34041, 34042, null );\r\n\t\t\t\t\text.framebufferTextureMultiviewOVR( 36160, 33306, depthStencilTexture, 0, 0, numViews );\r\n\r\n\t\t\t\t\tvar viewFramebuffers = new Array( numViews );\r\n\t\t\t\t\tfor ( var i = 0; i < numViews; ++ i ) {\r\n\r\n\t\t\t\t\t\tviewFramebuffers[ i ] = _gl.createFramebuffer();\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, viewFramebuffers[ i ] );\r\n\t\t\t\t\t\t_gl.framebufferTextureLayer( 36160, 36064, colorTexture, 0, i );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\trenderTargetProperties.__webglColorTexture = colorTexture;\r\n\t\t\t\t\trenderTargetProperties.__webglDepthStencilTexture = depthStencilTexture;\r\n\t\t\t\t\trenderTargetProperties.__webglViewFramebuffers = viewFramebuffers;\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, null );\r\n\t\t\t\t\t_gl.bindTexture( 35866, null );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Setup color buffer\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\tstate.bindTexture( 34067, textureProperties.__webglTexture );\r\n\t\t\t\tsetTextureParameters( 34067, renderTarget.texture, supportsMips );\r\n\r\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\r\n\r\n\t\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, 36064, 34069 + i );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\tgenerateMipmap( 34067, renderTarget.texture, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.bindTexture( 34067, null );\r\n\r\n\t\t\t} else if ( ! isMultiview ) {\r\n\r\n\t\t\t\tstate.bindTexture( 3553, textureProperties.__webglTexture );\r\n\t\t\t\tsetTextureParameters( 3553, renderTarget.texture, supportsMips );\r\n\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, 36064, 3553 );\r\n\r\n\t\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\r\n\r\n\t\t\t\t\tgenerateMipmap( 3553, renderTarget.texture, renderTarget.width, renderTarget.height );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tstate.bindTexture( 3553, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Setup depth and stencil buffers\r\n\r\n\t\t\tif ( renderTarget.depthBuffer ) {\r\n\r\n\t\t\t\tsetupDepthRenderbuffer( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateRenderTargetMipmap( renderTarget ) {\r\n\r\n\t\t\tvar texture = renderTarget.texture;\r\n\t\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\r\n\r\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\r\n\r\n\t\t\t\tvar target = renderTarget.isWebGLRenderTargetCube ? 34067 : 3553;\r\n\t\t\t\tvar webglTexture = properties.get( texture ).__webglTexture;\r\n\r\n\t\t\t\tstate.bindTexture( target, webglTexture );\r\n\t\t\t\tgenerateMipmap( target, texture, renderTarget.width, renderTarget.height );\r\n\t\t\t\tstate.bindTexture( target, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateMultisampleRenderTarget( renderTarget ) {\r\n\r\n\t\t\tif ( renderTarget.isWebGLMultisampleRenderTarget ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) {\r\n\r\n\t\t\t\t\tvar renderTargetProperties = properties.get( renderTarget );\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36008, renderTargetProperties.__webglMultisampledFramebuffer );\r\n\t\t\t\t\t_gl.bindFramebuffer( 36009, renderTargetProperties.__webglFramebuffer );\r\n\r\n\t\t\t\t\tvar width = renderTarget.width;\r\n\t\t\t\t\tvar height = renderTarget.height;\r\n\t\t\t\t\tvar mask = 16384;\r\n\r\n\t\t\t\t\tif ( renderTarget.depthBuffer ) { mask |= 256; }\r\n\t\t\t\t\tif ( renderTarget.stencilBuffer ) { mask |= 1024; }\r\n\r\n\t\t\t\t\t_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, 9728 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction getRenderTargetSamples( renderTarget ) {\r\n\r\n\t\t\treturn ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?\r\n\t\t\t\tMath.min( maxSamples, renderTarget.samples ) : 0;\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateVideoTexture( texture ) {\r\n\r\n\t\t\tvar frame = info.render.frame;\r\n\r\n\t\t\t// Check the last frame we updated the VideoTexture\r\n\r\n\t\t\tif ( _videoTextures.get( texture ) !== frame ) {\r\n\r\n\t\t\t\t_videoTextures.set( texture, frame );\r\n\t\t\t\ttexture.update();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// backwards compatibility\r\n\r\n\t\tvar warnedTexture2D = false;\r\n\t\tvar warnedTextureCube = false;\r\n\r\n\t\tfunction safeSetTexture2D( texture, slot ) {\r\n\r\n\t\t\tif ( texture && texture.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\tif ( warnedTexture2D === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\twarnedTexture2D = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetTexture2D( texture, slot );\r\n\r\n\t\t}\r\n\r\n\t\tfunction safeSetTextureCube( texture, slot ) {\r\n\r\n\t\t\tif ( texture && texture.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\tif ( warnedTextureCube === false ) {\r\n\r\n\t\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\twarnedTextureCube = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture\r\n\t\t\t// TODO: unify these code paths\r\n\t\t\tif ( ( texture && texture.isCubeTexture ) ||\r\n\t\t\t\t( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {\r\n\r\n\t\t\t\t// CompressedTexture can have Array in image :/\r\n\r\n\t\t\t\t// this function alone should take care of cube textures\r\n\t\t\t\tsetTextureCube( texture, slot );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// assumed: texture property of THREE.WebGLRenderTargetCube\r\n\t\t\t\tsetTextureCubeDynamic( texture, slot );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.allocateTextureUnit = allocateTextureUnit;\r\n\t\tthis.resetTextureUnits = resetTextureUnits;\r\n\r\n\t\tthis.setTexture2D = setTexture2D;\r\n\t\tthis.setTexture2DArray = setTexture2DArray;\r\n\t\tthis.setTexture3D = setTexture3D;\r\n\t\tthis.setTextureCube = setTextureCube;\r\n\t\tthis.setTextureCubeDynamic = setTextureCubeDynamic;\r\n\t\tthis.setupRenderTarget = setupRenderTarget;\r\n\t\tthis.updateRenderTargetMipmap = updateRenderTargetMipmap;\r\n\t\tthis.updateMultisampleRenderTarget = updateMultisampleRenderTarget;\r\n\r\n\t\tthis.safeSetTexture2D = safeSetTexture2D;\r\n\t\tthis.safeSetTextureCube = safeSetTextureCube;\r\n\r\n\t}\n\n\t/**\r\n\t * @author thespite / http://www.twitter.com/thespite\r\n\t */\r\n\r\n\tfunction WebGLUtils( gl, extensions, capabilities ) {\r\n\r\n\t\tvar isWebGL2 = capabilities.isWebGL2;\r\n\r\n\t\tfunction convert( p ) {\r\n\r\n\t\t\tvar extension;\r\n\r\n\t\t\tif ( p === UnsignedByteType ) { return 5121; }\r\n\t\t\tif ( p === UnsignedShort4444Type ) { return 32819; }\r\n\t\t\tif ( p === UnsignedShort5551Type ) { return 32820; }\r\n\t\t\tif ( p === UnsignedShort565Type ) { return 33635; }\r\n\r\n\t\t\tif ( p === ByteType ) { return 5120; }\r\n\t\t\tif ( p === ShortType ) { return 5122; }\r\n\t\t\tif ( p === UnsignedShortType ) { return 5123; }\r\n\t\t\tif ( p === IntType ) { return 5124; }\r\n\t\t\tif ( p === UnsignedIntType ) { return 5125; }\r\n\t\t\tif ( p === FloatType ) { return 5126; }\r\n\r\n\t\t\tif ( p === HalfFloatType ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) { return 5131; }\r\n\r\n\t\t\t\textension = extensions.get( 'OES_texture_half_float' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.HALF_FLOAT_OES;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === AlphaFormat ) { return 6406; }\r\n\t\t\tif ( p === RGBFormat ) { return 6407; }\r\n\t\t\tif ( p === RGBAFormat ) { return 6408; }\r\n\t\t\tif ( p === LuminanceFormat ) { return 6409; }\r\n\t\t\tif ( p === LuminanceAlphaFormat ) { return 6410; }\r\n\t\t\tif ( p === DepthFormat ) { return 6402; }\r\n\t\t\tif ( p === DepthStencilFormat ) { return 34041; }\r\n\t\t\tif ( p === RedFormat ) { return 6403; }\r\n\r\n\t\t\tif ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||\r\n\t\t\t\tp === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_s3tc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\tif ( p === RGB_S3TC_DXT1_Format ) { return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT1_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT3_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; }\r\n\t\t\t\t\tif ( p === RGBA_S3TC_DXT5_Format ) { return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; }\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||\r\n\t\t\t\tp === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format ) { return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGB_PVRTC_2BPPV1_Format ) { return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGBA_PVRTC_4BPPV1_Format ) { return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; }\r\n\t\t\t\t\tif ( p === RGBA_PVRTC_2BPPV1_Format ) { return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; }\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGB_ETC1_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc1' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.COMPRESSED_RGB_ETC1_WEBGL;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||\r\n\t\t\t\tp === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||\r\n\t\t\t\tp === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) {\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_compressed_texture_astc' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\t// TODO Complete?\r\n\r\n\t\t\t\t\treturn p;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( p === UnsignedInt248Type ) {\r\n\r\n\t\t\t\tif ( isWebGL2 ) { return 34042; }\r\n\r\n\t\t\t\textension = extensions.get( 'WEBGL_depth_texture' );\r\n\r\n\t\t\t\tif ( extension !== null ) {\r\n\r\n\t\t\t\t\treturn extension.UNSIGNED_INT_24_8_WEBGL;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn { convert: convert };\r\n\r\n\t}\n\n\t/**\r\n\t * @author fernandojsg / http://fernandojsg.com\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction WebGLMultiviewRenderTarget( width, height, numViews, options ) {\r\n\r\n\t\tWebGLRenderTarget.call( this, width, height, options );\r\n\r\n\t\tthis.depthBuffer = false;\r\n\t\tthis.stencilBuffer = false;\r\n\r\n\t\tthis.numViews = numViews;\r\n\r\n\t}\r\n\r\n\tWebGLMultiviewRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {\r\n\r\n\t\tconstructor: WebGLMultiviewRenderTarget,\r\n\r\n\t\tisWebGLMultiviewRenderTarget: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tWebGLRenderTarget.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.numViews = source.numViews;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetNumViews: function ( numViews ) {\r\n\r\n\t\t\tif ( this.numViews !== numViews ) {\r\n\r\n\t\t\t\tthis.numViews = numViews;\r\n\t\t\t\tthis.dispose();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author fernandojsg / http://fernandojsg.com\r\n\t * @author Takahiro https://github.com/takahirox\r\n\t */\r\n\r\n\tfunction WebGLMultiview( renderer, gl ) {\r\n\r\n\t\tvar DEFAULT_NUMVIEWS = 2;\r\n\r\n\t\tvar extensions = renderer.extensions;\r\n\t\tvar properties = renderer.properties;\r\n\r\n\t\tvar renderTarget, currentRenderTarget;\r\n\t\tvar mat3, mat4, cameraArray, renderSize;\r\n\r\n\t\tvar available;\r\n\t\tvar maxNumViews = 0;\r\n\r\n\t\t//\r\n\r\n\t\tfunction isAvailable() {\r\n\r\n\t\t\tif ( available === undefined ) {\r\n\r\n\t\t\t\tvar extension = extensions.get( 'OVR_multiview2' );\r\n\r\n\t\t\t\tavailable = extension !== null && gl.getContextAttributes().antialias === false;\r\n\r\n\t\t\t\tif ( available ) {\r\n\r\n\t\t\t\t\tmaxNumViews = gl.getParameter( extension.MAX_VIEWS_OVR );\r\n\t\t\t\t\trenderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );\r\n\r\n\t\t\t\t\trenderSize = new Vector2();\r\n\t\t\t\t\tmat4 = [];\r\n\t\t\t\t\tmat3 = [];\r\n\t\t\t\t\tcameraArray = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < maxNumViews; i ++ ) {\r\n\r\n\t\t\t\t\t\tmat4[ i ] = new Matrix4();\r\n\t\t\t\t\t\tmat3[ i ] = new Matrix3();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn available;\r\n\r\n\t\t}\r\n\r\n\t\tfunction getCameraArray( camera ) {\r\n\r\n\t\t\tif ( camera.isArrayCamera ) { return camera.cameras; }\r\n\r\n\t\t\tcameraArray[ 0 ] = camera;\r\n\r\n\t\t\treturn cameraArray;\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateCameraProjectionMatricesUniform( camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].copy( cameras[ i ].projectionMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'projectionMatrices', mat4 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateCameraViewMatricesUniform( camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].copy( cameras[ i ].matrixWorldInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'viewMatrices', mat4 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateObjectMatricesUniforms( object, camera, uniforms ) {\r\n\r\n\t\t\tvar cameras = getCameraArray( camera );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tmat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );\r\n\t\t\t\tmat3[ i ].getNormalMatrix( mat4[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.setValue( gl, 'modelViewMatrices', mat4 );\r\n\t\t\tuniforms.setValue( gl, 'normalMatrices', mat3 );\r\n\r\n\t\t}\r\n\r\n\t\tfunction isMultiviewCompatible( camera ) {\r\n\r\n\t\t\tif ( camera.isArrayCamera === undefined ) { return true; }\r\n\r\n\t\t\tvar cameras = camera.cameras;\r\n\r\n\t\t\tif ( cameras.length > maxNumViews ) { return false; }\r\n\r\n\t\t\tfor ( var i = 1, il = cameras.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tif ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||\r\n\t\t\t\t\tcameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) { return false; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t}\r\n\r\n\t\tfunction resizeRenderTarget( camera ) {\r\n\r\n\t\t\tif ( currentRenderTarget ) {\r\n\r\n\t\t\t\trenderSize.set( currentRenderTarget.width, currentRenderTarget.height );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderer.getDrawingBufferSize( renderSize );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\tvar viewport = camera.cameras[ 0 ].viewport;\r\n\r\n\t\t\t\trenderTarget.setSize( viewport.z, viewport.w );\r\n\t\t\t\trenderTarget.setNumViews( camera.cameras.length );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderTarget.setSize( renderSize.x, renderSize.y );\r\n\t\t\t\trenderTarget.setNumViews( DEFAULT_NUMVIEWS );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction attachCamera( camera ) {\r\n\r\n\t\t\tif ( isMultiviewCompatible( camera ) === false ) { return; }\r\n\r\n\t\t\tcurrentRenderTarget = renderer.getRenderTarget();\r\n\t\t\tresizeRenderTarget( camera );\r\n\t\t\trenderer.setRenderTarget( renderTarget );\r\n\r\n\t\t}\r\n\r\n\t\tfunction detachCamera( camera ) {\r\n\r\n\t\t\tif ( renderTarget !== renderer.getRenderTarget() ) { return; }\r\n\r\n\t\t\trenderer.setRenderTarget( currentRenderTarget );\r\n\r\n\t\t\tflush( camera );\r\n\r\n\t\t}\r\n\r\n\t\tfunction flush( camera ) {\r\n\r\n\t\t\tvar srcRenderTarget = renderTarget;\r\n\t\t\tvar numViews = srcRenderTarget.numViews;\r\n\r\n\t\t\tvar srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;\r\n\r\n\t\t\tvar viewWidth = srcRenderTarget.width;\r\n\t\t\tvar viewHeight = srcRenderTarget.height;\r\n\r\n\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < numViews; i ++ ) {\r\n\r\n\t\t\t\t\tvar viewport = camera.cameras[ i ].viewport;\r\n\r\n\t\t\t\t\tvar x1 = viewport.x;\r\n\t\t\t\t\tvar y1 = viewport.y;\r\n\t\t\t\t\tvar x2 = x1 + viewport.z;\r\n\t\t\t\t\tvar y2 = y1 + viewport.w;\r\n\r\n\t\t\t\t\tgl.bindFramebuffer( 36008, srcFramebuffers[ i ] );\r\n\t\t\t\t\tgl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, 16384, 9728 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tgl.bindFramebuffer( 36008, srcFramebuffers[ 0 ] );\r\n\t\t\t\tgl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, 16384, 9728 );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.isAvailable = isAvailable;\r\n\t\tthis.attachCamera = attachCamera;\r\n\t\tthis.detachCamera = detachCamera;\r\n\t\tthis.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;\r\n\t\tthis.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;\r\n\t\tthis.updateObjectMatricesUniforms = updateObjectMatricesUniforms;\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Group() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Group';\r\n\r\n\t}\r\n\r\n\tGroup.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Group,\r\n\r\n\t\tisGroup: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ArrayCamera( array ) {\r\n\r\n\t\tPerspectiveCamera.call( this );\r\n\r\n\t\tthis.cameras = array || [];\r\n\r\n\t}\r\n\r\n\tArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {\r\n\r\n\t\tconstructor: ArrayCamera,\r\n\r\n\t\tisArrayCamera: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author jsantell / https://www.jsantell.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar cameraLPos = new Vector3();\r\n\tvar cameraRPos = new Vector3();\r\n\r\n\t/**\r\n\t * Assumes 2 cameras that are parallel and share an X-axis, and that\r\n\t * the cameras' projection and world matrices have already been set.\r\n\t * And that near and far planes are identical for both cameras.\r\n\t * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765\r\n\t */\r\n\tfunction setProjectionFromUnion( camera, cameraL, cameraR ) {\r\n\r\n\t\tcameraLPos.setFromMatrixPosition( cameraL.matrixWorld );\r\n\t\tcameraRPos.setFromMatrixPosition( cameraR.matrixWorld );\r\n\r\n\t\tvar ipd = cameraLPos.distanceTo( cameraRPos );\r\n\r\n\t\tvar projL = cameraL.projectionMatrix.elements;\r\n\t\tvar projR = cameraR.projectionMatrix.elements;\r\n\r\n\t\t// VR systems will have identical far and near planes, and\r\n\t\t// most likely identical top and bottom frustum extents.\r\n\t\t// Use the left camera for these values.\r\n\t\tvar near = projL[ 14 ] / ( projL[ 10 ] - 1 );\r\n\t\tvar far = projL[ 14 ] / ( projL[ 10 ] + 1 );\r\n\t\tvar topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];\r\n\t\tvar bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];\r\n\r\n\t\tvar leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];\r\n\t\tvar rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];\r\n\t\tvar left = near * leftFov;\r\n\t\tvar right = near * rightFov;\r\n\r\n\t\t// Calculate the new camera's position offset from the\r\n\t\t// left camera. xOffset should be roughly half `ipd`.\r\n\t\tvar zOffset = ipd / ( - leftFov + rightFov );\r\n\t\tvar xOffset = zOffset * - leftFov;\r\n\r\n\t\t// TODO: Better way to apply this offset?\r\n\t\tcameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );\r\n\t\tcamera.translateX( xOffset );\r\n\t\tcamera.translateZ( zOffset );\r\n\t\tcamera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );\r\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\r\n\r\n\t\t// Find the union of the frustum values of the cameras and scale\r\n\t\t// the values so that the near plane's position does not change in world space,\r\n\t\t// although must now be relative to the new union camera.\r\n\t\tvar near2 = near + zOffset;\r\n\t\tvar far2 = far + zOffset;\r\n\t\tvar left2 = left - xOffset;\r\n\t\tvar right2 = right + ( ipd - xOffset );\r\n\t\tvar top2 = topFov * far / far2 * near2;\r\n\t\tvar bottom2 = bottomFov * far / far2 * near2;\r\n\r\n\t\tcamera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebVRManager( renderer ) {\r\n\r\n\t\tvar renderWidth, renderHeight;\r\n\t\tvar scope = this;\r\n\r\n\t\tvar device = null;\r\n\t\tvar frameData = null;\r\n\r\n\t\tvar poseTarget = null;\r\n\r\n\t\tvar controllers = [];\r\n\t\tvar standingMatrix = new Matrix4();\r\n\t\tvar standingMatrixInverse = new Matrix4();\r\n\r\n\t\tvar framebufferScaleFactor = 1.0;\r\n\r\n\t\tvar referenceSpaceType = 'local-floor';\r\n\r\n\t\tif ( typeof window !== 'undefined' && 'VRFrameData' in window ) {\r\n\r\n\t\t\tframeData = new window.VRFrameData();\r\n\t\t\twindow.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false );\r\n\r\n\t\t}\r\n\r\n\t\tvar matrixWorldInverse = new Matrix4();\r\n\t\tvar tempQuaternion = new Quaternion();\r\n\t\tvar tempPosition = new Vector3();\r\n\r\n\t\tvar cameraL = new PerspectiveCamera();\r\n\t\tcameraL.viewport = new Vector4();\r\n\t\tcameraL.layers.enable( 1 );\r\n\r\n\t\tvar cameraR = new PerspectiveCamera();\r\n\t\tcameraR.viewport = new Vector4();\r\n\t\tcameraR.layers.enable( 2 );\r\n\r\n\t\tvar cameraVR = new ArrayCamera( [ cameraL, cameraR ] );\r\n\t\tcameraVR.layers.enable( 1 );\r\n\t\tcameraVR.layers.enable( 2 );\r\n\r\n\t\t//\r\n\r\n\t\tfunction isPresenting() {\r\n\r\n\t\t\treturn device !== null && device.isPresenting === true;\r\n\r\n\t\t}\r\n\r\n\t\tvar currentSize = new Vector2(), currentPixelRatio;\r\n\r\n\t\tfunction onVRDisplayPresentChange() {\r\n\r\n\t\t\tif ( isPresenting() ) {\r\n\r\n\t\t\t\tvar eyeParameters = device.getEyeParameters( 'left' );\r\n\t\t\t\trenderWidth = 2 * eyeParameters.renderWidth * framebufferScaleFactor;\r\n\t\t\t\trenderHeight = eyeParameters.renderHeight * framebufferScaleFactor;\r\n\r\n\t\t\t\tcurrentPixelRatio = renderer.getPixelRatio();\r\n\t\t\t\trenderer.getSize( currentSize );\r\n\r\n\t\t\t\trenderer.setDrawingBufferSize( renderWidth, renderHeight, 1 );\r\n\r\n\t\t\t\tcameraL.viewport.set( 0, 0, renderWidth / 2, renderHeight );\r\n\t\t\t\tcameraR.viewport.set( renderWidth / 2, 0, renderWidth / 2, renderHeight );\r\n\r\n\t\t\t\tanimation.start();\r\n\r\n\t\t\t\tscope.dispatchEvent( { type: 'sessionstart' } );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( scope.enabled ) {\r\n\r\n\t\t\t\t\trenderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tanimation.stop();\r\n\r\n\t\t\t\tscope.dispatchEvent( { type: 'sessionend' } );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar triggers = [];\r\n\t\tvar grips = [];\r\n\r\n\t\tfunction findGamepad( id ) {\r\n\r\n\t\t\tvar gamepads = navigator.getGamepads && navigator.getGamepads();\r\n\r\n\t\t\tfor ( var i = 0, l = gamepads.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar gamepad = gamepads[ i ];\r\n\r\n\t\t\t\tif ( gamepad && ( gamepad.id === 'Daydream Controller' ||\r\n\t\t\t\t\tgamepad.id === 'Gear VR Controller' || gamepad.id === 'Oculus Go Controller' ||\r\n\t\t\t\t\tgamepad.id === 'OpenVR Gamepad' || gamepad.id.startsWith( 'Oculus Touch' ) ||\r\n\t\t\t\t\tgamepad.id.startsWith( 'HTC Vive Focus' ) ||\r\n\t\t\t\t\tgamepad.id.startsWith( 'Spatial Controller' ) ) ) {\r\n\r\n\t\t\t\t\tvar hand = gamepad.hand;\r\n\r\n\t\t\t\t\tif ( id === 0 && ( hand === '' || hand === 'right' ) ) { return gamepad; }\r\n\t\t\t\t\tif ( id === 1 && ( hand === 'left' ) ) { return gamepad; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateControllers() {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tvar controller = controllers[ i ];\r\n\r\n\t\t\t\tvar gamepad = findGamepad( i );\r\n\r\n\t\t\t\tif ( gamepad !== undefined && gamepad.pose !== undefined ) {\r\n\r\n\t\t\t\t\tif ( gamepad.pose === null ) { return; }\r\n\r\n\t\t\t\t\t// Pose\r\n\r\n\t\t\t\t\tvar pose = gamepad.pose;\r\n\r\n\t\t\t\t\tif ( pose.hasPosition === false ) { controller.position.set( 0.2, - 0.6, - 0.05 ); }\r\n\r\n\t\t\t\t\tif ( pose.position !== null ) { controller.position.fromArray( pose.position ); }\r\n\t\t\t\t\tif ( pose.orientation !== null ) { controller.quaternion.fromArray( pose.orientation ); }\r\n\t\t\t\t\tcontroller.matrix.compose( controller.position, controller.quaternion, controller.scale );\r\n\t\t\t\t\tcontroller.matrix.premultiply( standingMatrix );\r\n\t\t\t\t\tcontroller.matrix.decompose( controller.position, controller.quaternion, controller.scale );\r\n\t\t\t\t\tcontroller.matrixWorldNeedsUpdate = true;\r\n\t\t\t\t\tcontroller.visible = true;\r\n\r\n\t\t\t\t\t// Trigger\r\n\r\n\t\t\t\t\tvar buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;\r\n\r\n\t\t\t\t\tif ( triggers[ i ] === undefined ) { triggers[ i ] = false; }\r\n\r\n\t\t\t\t\tif ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {\r\n\r\n\t\t\t\t\t\ttriggers[ i ] = gamepad.buttons[ buttonId ].pressed;\r\n\r\n\t\t\t\t\t\tif ( triggers[ i ] === true ) {\r\n\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'selectstart' } );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'selectend' } );\r\n\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'select' } );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Grip\r\n\t\t\t\t\tbuttonId = 2;\r\n\r\n\t\t\t\t\tif ( grips[ i ] === undefined ) { grips[ i ] = false; }\r\n\r\n\t\t\t\t\t// Skip if the grip button doesn't exist on this controller\r\n\t\t\t\t\tif ( gamepad.buttons[ buttonId ] !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( grips[ i ] !== gamepad.buttons[ buttonId ].pressed ) {\r\n\r\n\t\t\t\t\t\t\tgrips[ i ] = gamepad.buttons[ buttonId ].pressed;\r\n\r\n\t\t\t\t\t\t\tif ( grips[ i ] === true ) {\r\n\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeezestart' } );\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeezeend' } );\r\n\t\t\t\t\t\t\t\tcontroller.dispatchEvent( { type: 'squeeze' } );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction updateViewportFromBounds( viewport, bounds ) {\r\n\r\n\t\t\tif ( bounds !== null && bounds.length === 4 ) {\r\n\r\n\t\t\t\tviewport.set( bounds[ 0 ] * renderWidth, bounds[ 1 ] * renderHeight, bounds[ 2 ] * renderWidth, bounds[ 3 ] * renderHeight );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.getController = function ( id ) {\r\n\r\n\t\t\tvar controller = controllers[ id ];\r\n\r\n\t\t\tif ( controller === undefined ) {\r\n\r\n\t\t\t\tcontroller = new Group();\r\n\t\t\t\tcontroller.matrixAutoUpdate = false;\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\tcontrollers[ id ] = controller;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn controller;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDevice = function () {\r\n\r\n\t\t\treturn device;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDevice = function ( value ) {\r\n\r\n\t\t\tif ( value !== undefined ) { device = value; }\r\n\r\n\t\t\tanimation.setContext( value );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setFramebufferScaleFactor = function ( value ) {\r\n\r\n\t\t\tframebufferScaleFactor = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setReferenceSpaceType = function ( value ) {\r\n\r\n\t\t\treferenceSpaceType = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setPoseTarget = function ( object ) {\r\n\r\n\t\t\tif ( object !== undefined ) { poseTarget = object; }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCamera = function ( camera ) {\r\n\r\n\t\t\tvar userHeight = referenceSpaceType === 'local-floor' ? 1.6 : 0;\r\n\r\n\t\t\tdevice.depthNear = camera.near;\r\n\t\t\tdevice.depthFar = camera.far;\r\n\r\n\t\t\tdevice.getFrameData( frameData );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( referenceSpaceType === 'local-floor' ) {\r\n\r\n\t\t\t\tvar stageParameters = device.stageParameters;\r\n\r\n\t\t\t\tif ( stageParameters ) {\r\n\r\n\t\t\t\t\tstandingMatrix.fromArray( stageParameters.sittingToStandingTransform );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tstandingMatrix.makeTranslation( 0, userHeight, 0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar pose = frameData.pose;\r\n\t\t\tvar poseObject = poseTarget !== null ? poseTarget : camera;\r\n\r\n\t\t\t// We want to manipulate poseObject by its position and quaternion components since users may rely on them.\r\n\t\t\tposeObject.matrix.copy( standingMatrix );\r\n\t\t\tposeObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale );\r\n\r\n\t\t\tif ( pose.orientation !== null ) {\r\n\r\n\t\t\t\ttempQuaternion.fromArray( pose.orientation );\r\n\t\t\t\tposeObject.quaternion.multiply( tempQuaternion );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( pose.position !== null ) {\r\n\r\n\t\t\t\ttempQuaternion.setFromRotationMatrix( standingMatrix );\r\n\t\t\t\ttempPosition.fromArray( pose.position );\r\n\t\t\t\ttempPosition.applyQuaternion( tempQuaternion );\r\n\t\t\t\tposeObject.position.add( tempPosition );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tposeObject.updateMatrixWorld();\r\n\r\n\t\t\tvar children = poseObject.children;\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( true );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tcameraL.near = camera.near;\r\n\t\t\tcameraR.near = camera.near;\r\n\r\n\t\t\tcameraL.far = camera.far;\r\n\t\t\tcameraR.far = camera.far;\r\n\r\n\t\t\tcameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );\r\n\t\t\tcameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );\r\n\r\n\t\t\t// TODO (mrdoob) Double check this code\r\n\r\n\t\t\tstandingMatrixInverse.getInverse( standingMatrix );\r\n\r\n\t\t\tif ( referenceSpaceType === 'local-floor' ) {\r\n\r\n\t\t\t\tcameraL.matrixWorldInverse.multiply( standingMatrixInverse );\r\n\t\t\t\tcameraR.matrixWorldInverse.multiply( standingMatrixInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parent = poseObject.parent;\r\n\r\n\t\t\tif ( parent !== null ) {\r\n\r\n\t\t\t\tmatrixWorldInverse.getInverse( parent.matrixWorld );\r\n\r\n\t\t\t\tcameraL.matrixWorldInverse.multiply( matrixWorldInverse );\r\n\t\t\t\tcameraR.matrixWorldInverse.multiply( matrixWorldInverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// envMap and Mirror needs camera.matrixWorld\r\n\r\n\t\t\tcameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse );\r\n\t\t\tcameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse );\r\n\r\n\t\t\tcameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );\r\n\t\t\tcameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );\r\n\r\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar layers = device.getLayers();\r\n\r\n\t\t\tif ( layers.length ) {\r\n\r\n\t\t\t\tvar layer = layers[ 0 ];\r\n\r\n\t\t\t\tupdateViewportFromBounds( cameraL.viewport, layer.leftBounds );\r\n\t\t\t\tupdateViewportFromBounds( cameraR.viewport, layer.rightBounds );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tupdateControllers();\r\n\r\n\t\t\treturn cameraVR;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getStandingMatrix = function () {\r\n\r\n\t\t\treturn standingMatrix;\r\n\r\n\t\t};\r\n\r\n\t\tthis.isPresenting = isPresenting;\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tanimation.setAnimationLoop( callback );\r\n\r\n\t\t\tif ( isPresenting() ) { animation.start(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.submitFrame = function () {\r\n\r\n\t\t\tif ( isPresenting() ) { device.submitFrame(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.dispose = function () {\r\n\r\n\t\t\tif ( typeof window !== 'undefined' ) {\r\n\r\n\t\t\t\twindow.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\t// DEPRECATED\r\n\r\n\t\tthis.setFrameOfReferenceType = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebVRManager: setFrameOfReferenceType() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( WebVRManager.prototype, EventDispatcher.prototype );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction WebXRManager( renderer, gl ) {\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar session = null;\r\n\r\n\t\t// var framebufferScaleFactor = 1.0;\r\n\r\n\t\tvar referenceSpace = null;\r\n\t\tvar referenceSpaceType = 'local-floor';\r\n\r\n\t\tvar pose = null;\r\n\t\tvar poseTarget = null;\r\n\r\n\t\tvar controllers = [];\r\n\t\tvar sortedInputSources = [];\r\n\r\n\t\tfunction isPresenting() {\r\n\r\n\t\t\treturn session !== null && referenceSpace !== null;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar cameraL = new PerspectiveCamera();\r\n\t\tcameraL.layers.enable( 1 );\r\n\t\tcameraL.viewport = new Vector4();\r\n\r\n\t\tvar cameraR = new PerspectiveCamera();\r\n\t\tcameraR.layers.enable( 2 );\r\n\t\tcameraR.viewport = new Vector4();\r\n\r\n\t\tvar cameraVR = new ArrayCamera( [ cameraL, cameraR ] );\r\n\t\tcameraVR.layers.enable( 1 );\r\n\t\tcameraVR.layers.enable( 2 );\r\n\r\n\t\tvar _currentDepthNear = null;\r\n\t\tvar _currentDepthFar = null;\r\n\r\n\t\t//\r\n\r\n\t\tthis.enabled = false;\r\n\r\n\t\tthis.getController = function ( id ) {\r\n\r\n\t\t\tvar controller = controllers[ id ];\r\n\r\n\t\t\tif ( controller === undefined ) {\r\n\r\n\t\t\t\tcontroller = new Group();\r\n\t\t\t\tcontroller.matrixAutoUpdate = false;\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t\tcontrollers[ id ] = controller;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn controller;\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tfunction onSessionEvent( event ) {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tif ( sortedInputSources[ i ] === event.inputSource ) {\r\n\r\n\t\t\t\t\tcontrollers[ i ].dispatchEvent( { type: event.type } );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction onSessionEnd() {\r\n\r\n\t\t\trenderer.setFramebuffer( null );\r\n\t\t\trenderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830\r\n\t\t\tanimation.stop();\r\n\r\n\t\t\tscope.dispatchEvent( { type: 'sessionend' } );\r\n\r\n\t\t}\r\n\r\n\t\tfunction onRequestReferenceSpace( value ) {\r\n\r\n\t\t\treferenceSpace = value;\r\n\r\n\t\t\tanimation.setContext( session );\r\n\t\t\tanimation.start();\r\n\r\n\t\t\tscope.dispatchEvent( { type: 'sessionstart' } );\r\n\r\n\t\t}\r\n\r\n\t\tthis.setFramebufferScaleFactor = function ( /* value */ ) {\r\n\r\n\t\t\t// framebufferScaleFactor = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setReferenceSpaceType = function ( value ) {\r\n\r\n\t\t\treferenceSpaceType = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getSession = function () {\r\n\r\n\t\t\treturn session;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setSession = function ( value ) {\r\n\r\n\t\t\tsession = value;\r\n\r\n\t\t\tif ( session !== null ) {\r\n\r\n\t\t\t\tsession.addEventListener( 'select', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'selectstart', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'selectend', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeeze', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeezestart', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'squeezeend', onSessionEvent );\r\n\t\t\t\tsession.addEventListener( 'end', onSessionEnd );\r\n\r\n\t\t\t\t// eslint-disable-next-line no-undef\r\n\t\t\t\tsession.updateRenderState( { baseLayer: new XRWebGLLayer( session, gl,\r\n\t\t\t\t\t{\r\n\t\t\t\t\t\tantialias: gl.getContextAttributes().antialias,\r\n\t\t\t\t\t\talpha: gl.getContextAttributes().alpha,\r\n\t\t\t\t\t\tdepth: gl.getContextAttributes().depth,\r\n\t\t\t\t\t\tstencil: gl.getContextAttributes().stencil\r\n\t\t\t\t\t}\r\n\t\t\t\t) } );\r\n\r\n\t\t\t\tsession.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );\r\n\r\n\t\t\t\t//\r\n\r\n\t\t\t\tsession.addEventListener( 'inputsourceschange', updateInputSources );\r\n\r\n\t\t\t\tupdateInputSources();\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tfunction updateInputSources() {\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tsortedInputSources[ i ] = findInputSource( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction findInputSource( id ) {\r\n\r\n\t\t\tvar inputSources = session.inputSources;\r\n\r\n\t\t\tfor ( var i = 0; i < inputSources.length; i ++ ) {\r\n\r\n\t\t\t\tvar inputSource = inputSources[ i ];\r\n\t\t\t\tvar handedness = inputSource.handedness;\r\n\r\n\t\t\t\tif ( id === 0 && ( handedness === 'none' || handedness === 'right' ) ) { return inputSource; }\r\n\t\t\t\tif ( id === 1 && ( handedness === 'left' ) ) { return inputSource; }\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tfunction updateCamera( camera, parent ) {\r\n\r\n\t\t\tif ( parent === null ) {\r\n\r\n\t\t\t\tcamera.matrixWorld.copy( camera.matrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tcamera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\r\n\r\n\t\t}\r\n\r\n\t\tthis.setPoseTarget = function ( object ) {\r\n\r\n\t\t\tif ( object !== undefined ) { poseTarget = object; }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCamera = function ( camera ) {\r\n\r\n\t\t\tcameraVR.near = cameraR.near = cameraL.near = camera.near;\r\n\t\t\tcameraVR.far = cameraR.far = cameraL.far = camera.far;\r\n\t\t\tif ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {\r\n\r\n\t\t\t\tsession.updateRenderState( {\r\n\t\t\t\t\tdepthNear: cameraVR.near,\r\n\t\t\t\t\tdepthFar: cameraVR.far\r\n\t\t\t\t} );\r\n\r\n\t\t\t\t_currentDepthNear = cameraVR.near;\r\n\t\t\t\t_currentDepthFar = cameraVR.far;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parent = camera.parent;\r\n\t\t\tvar cameras = cameraVR.cameras;\r\n\t\t\tvar object = poseTarget || camera;\r\n\r\n\t\t\tupdateCamera( cameraVR, parent );\r\n\r\n\t\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\r\n\r\n\t\t\t\tupdateCamera( cameras[ i ], parent );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update camera and its children\r\n\t\t\tobject.matrixWorld.copy( cameraVR.matrixWorld );\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tchildren[ i ].updateMatrixWorld( true );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\r\n\r\n\t\t\treturn cameraVR;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCameraPose = function ( ) {\r\n\r\n\t\t\treturn pose;\r\n\r\n\t\t};\r\n\r\n\t\tthis.isPresenting = isPresenting;\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar onAnimationFrameCallback = null;\r\n\r\n\t\tfunction onAnimationFrame( time, frame ) {\r\n\r\n\t\t\tpose = frame.getViewerPose( referenceSpace );\r\n\r\n\t\t\tif ( pose !== null ) {\r\n\r\n\t\t\t\tvar views = pose.views;\r\n\t\t\t\tvar baseLayer = session.renderState.baseLayer;\r\n\r\n\t\t\t\trenderer.setFramebuffer( baseLayer.framebuffer );\r\n\r\n\t\t\t\tfor ( var i = 0; i < views.length; i ++ ) {\r\n\r\n\t\t\t\t\tvar view = views[ i ];\r\n\t\t\t\t\tvar viewport = baseLayer.getViewport( view );\r\n\t\t\t\t\tvar viewMatrix = view.transform.inverse.matrix;\r\n\r\n\t\t\t\t\tvar camera = cameraVR.cameras[ i ];\r\n\t\t\t\t\tcamera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix );\r\n\t\t\t\t\tcamera.projectionMatrix.fromArray( view.projectionMatrix );\r\n\t\t\t\t\tcamera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );\r\n\r\n\t\t\t\t\tif ( i === 0 ) {\r\n\r\n\t\t\t\t\t\tcameraVR.matrix.copy( camera.matrix );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\r\n\r\n\t\t\t\tvar controller = controllers[ i ];\r\n\r\n\t\t\t\tvar inputSource = sortedInputSources[ i ];\r\n\r\n\t\t\t\tif ( inputSource ) {\r\n\r\n\t\t\t\t\tvar inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );\r\n\r\n\t\t\t\t\tif ( inputPose !== null ) {\r\n\r\n\t\t\t\t\t\tcontroller.matrix.fromArray( inputPose.transform.matrix );\r\n\t\t\t\t\t\tcontroller.matrix.decompose( controller.position, controller.rotation, controller.scale );\r\n\t\t\t\t\t\tcontroller.visible = true;\r\n\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcontroller.visible = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( onAnimationFrameCallback ) { onAnimationFrameCallback( time, frame ); }\r\n\r\n\t\t}\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\t\tanimation.setAnimationLoop( onAnimationFrame );\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tonAnimationFrameCallback = callback;\r\n\r\n\t\t};\r\n\r\n\t\tthis.dispose = function () {};\r\n\r\n\t\t// DEPRECATED\r\n\r\n\t\tthis.getStandingMatrix = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' );\r\n\t\t\treturn new Matrix4();\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDevice = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: getDevice() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDevice = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: setDevice() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setFrameOfReferenceType = function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebXRManager: setFrameOfReferenceType() has been deprecated.' );\r\n\r\n\t\t};\r\n\r\n\t\tthis.submitFrame = function () {};\r\n\r\n\t}\r\n\r\n\tObject.assign( WebXRManager.prototype, EventDispatcher.prototype );\n\n\t/**\r\n\t * @author supereggbert / http://www.paulbrunt.co.uk/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author szimek / https://github.com/szimek/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction WebGLRenderer( parameters ) {\r\n\r\n\t\tparameters = parameters || {};\r\n\r\n\t\tvar _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),\r\n\t\t\t_context = parameters.context !== undefined ? parameters.context : null,\r\n\r\n\t\t\t_alpha = parameters.alpha !== undefined ? parameters.alpha : false,\r\n\t\t\t_depth = parameters.depth !== undefined ? parameters.depth : true,\r\n\t\t\t_stencil = parameters.stencil !== undefined ? parameters.stencil : true,\r\n\t\t\t_antialias = parameters.antialias !== undefined ? parameters.antialias : false,\r\n\t\t\t_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,\r\n\t\t\t_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,\r\n\t\t\t_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',\r\n\t\t\t_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;\r\n\r\n\t\tvar currentRenderList = null;\r\n\t\tvar currentRenderState = null;\r\n\r\n\t\t// public properties\r\n\r\n\t\tthis.domElement = _canvas;\r\n\r\n\t\t// Debug configuration container\r\n\t\tthis.debug = {\r\n\r\n\t\t\t/**\r\n\t\t\t * Enables error checking and reporting when shader programs are being compiled\r\n\t\t\t * @type {boolean}\r\n\t\t\t */\r\n\t\t\tcheckShaderErrors: true\r\n\t\t};\r\n\r\n\t\t// clearing\r\n\r\n\t\tthis.autoClear = true;\r\n\t\tthis.autoClearColor = true;\r\n\t\tthis.autoClearDepth = true;\r\n\t\tthis.autoClearStencil = true;\r\n\r\n\t\t// scene graph\r\n\r\n\t\tthis.sortObjects = true;\r\n\r\n\t\t// user-defined clipping\r\n\r\n\t\tthis.clippingPlanes = [];\r\n\t\tthis.localClippingEnabled = false;\r\n\r\n\t\t// physically based shading\r\n\r\n\t\tthis.gammaFactor = 2.0;\t// for backwards compatibility\r\n\t\tthis.gammaOutput = false;\r\n\r\n\t\t// physical lights\r\n\r\n\t\tthis.physicallyCorrectLights = false;\r\n\r\n\t\t// tone mapping\r\n\r\n\t\tthis.toneMapping = LinearToneMapping;\r\n\t\tthis.toneMappingExposure = 1.0;\r\n\t\tthis.toneMappingWhitePoint = 1.0;\r\n\r\n\t\t// morphs\r\n\r\n\t\tthis.maxMorphTargets = 8;\r\n\t\tthis.maxMorphNormals = 4;\r\n\r\n\t\t// internal properties\r\n\r\n\t\tvar _this = this,\r\n\r\n\t\t\t_isContextLost = false,\r\n\r\n\t\t\t// internal state cache\r\n\r\n\t\t\t_framebuffer = null,\r\n\r\n\t\t\t_currentActiveCubeFace = 0,\r\n\t\t\t_currentActiveMipmapLevel = 0,\r\n\t\t\t_currentRenderTarget = null,\r\n\t\t\t_currentFramebuffer = null,\r\n\t\t\t_currentMaterialId = - 1,\r\n\r\n\t\t\t// geometry and program caching\r\n\r\n\t\t\t_currentGeometryProgram = {\r\n\t\t\t\tgeometry: null,\r\n\t\t\t\tprogram: null,\r\n\t\t\t\twireframe: false\r\n\t\t\t},\r\n\r\n\t\t\t_currentCamera = null,\r\n\t\t\t_currentArrayCamera = null,\r\n\r\n\t\t\t_currentViewport = new Vector4(),\r\n\t\t\t_currentScissor = new Vector4(),\r\n\t\t\t_currentScissorTest = null,\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_width = _canvas.width,\r\n\t\t\t_height = _canvas.height,\r\n\r\n\t\t\t_pixelRatio = 1,\r\n\r\n\t\t\t_viewport = new Vector4( 0, 0, _width, _height ),\r\n\t\t\t_scissor = new Vector4( 0, 0, _width, _height ),\r\n\t\t\t_scissorTest = false,\r\n\r\n\t\t\t// frustum\r\n\r\n\t\t\t_frustum = new Frustum(),\r\n\r\n\t\t\t// clipping\r\n\r\n\t\t\t_clipping = new WebGLClipping(),\r\n\t\t\t_clippingEnabled = false,\r\n\t\t\t_localClippingEnabled = false,\r\n\r\n\t\t\t// camera matrices cache\r\n\r\n\t\t\t_projScreenMatrix = new Matrix4(),\r\n\r\n\t\t\t_vector3 = new Vector3();\r\n\r\n\t\tfunction getTargetPixelRatio() {\r\n\r\n\t\t\treturn _currentRenderTarget === null ? _pixelRatio : 1;\r\n\r\n\t\t}\r\n\r\n\t\t// initialize\r\n\r\n\t\tvar _gl;\r\n\r\n\t\ttry {\r\n\r\n\t\t\tvar contextAttributes = {\r\n\t\t\t\talpha: _alpha,\r\n\t\t\t\tdepth: _depth,\r\n\t\t\t\tstencil: _stencil,\r\n\t\t\t\tantialias: _antialias,\r\n\t\t\t\tpremultipliedAlpha: _premultipliedAlpha,\r\n\t\t\t\tpreserveDrawingBuffer: _preserveDrawingBuffer,\r\n\t\t\t\tpowerPreference: _powerPreference,\r\n\t\t\t\tfailIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat,\r\n\t\t\t\txrCompatible: true\r\n\t\t\t};\r\n\r\n\t\t\t// event listeners must be registered before WebGL context is created, see #12753\r\n\r\n\t\t\t_canvas.addEventListener( 'webglcontextlost', onContextLost, false );\r\n\t\t\t_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );\r\n\r\n\t\t\t_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );\r\n\r\n\t\t\tif ( _gl === null ) {\r\n\r\n\t\t\t\tif ( _canvas.getContext( 'webgl' ) !== null ) {\r\n\r\n\t\t\t\t\tthrow new Error( 'Error creating WebGL context with your selected attributes.' );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthrow new Error( 'Error creating WebGL context.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Some experimental-webgl implementations do not have getShaderPrecisionFormat\r\n\r\n\t\t\tif ( _gl.getShaderPrecisionFormat === undefined ) {\r\n\r\n\t\t\t\t_gl.getShaderPrecisionFormat = function () {\r\n\r\n\t\t\t\t\treturn { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t} catch ( error ) {\r\n\r\n\t\t\tconsole.error( 'THREE.WebGLRenderer: ' + error.message );\r\n\t\t\tthrow error;\r\n\r\n\t\t}\r\n\r\n\t\tvar extensions, capabilities, state, info;\r\n\t\tvar properties, textures, attributes, geometries, objects;\r\n\t\tvar programCache, renderLists, renderStates;\r\n\r\n\t\tvar background, morphtargets, bufferRenderer, indexedBufferRenderer;\r\n\r\n\t\tvar utils;\r\n\r\n\t\tfunction initGLContext() {\r\n\r\n\t\t\textensions = new WebGLExtensions( _gl );\r\n\r\n\t\t\tcapabilities = new WebGLCapabilities( _gl, extensions, parameters );\r\n\r\n\t\t\tif ( capabilities.isWebGL2 === false ) {\r\n\r\n\t\t\t\textensions.get( 'WEBGL_depth_texture' );\r\n\t\t\t\textensions.get( 'OES_texture_float' );\r\n\t\t\t\textensions.get( 'OES_texture_half_float' );\r\n\t\t\t\textensions.get( 'OES_texture_half_float_linear' );\r\n\t\t\t\textensions.get( 'OES_standard_derivatives' );\r\n\t\t\t\textensions.get( 'OES_element_index_uint' );\r\n\t\t\t\textensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\textensions.get( 'OES_texture_float_linear' );\r\n\r\n\t\t\tutils = new WebGLUtils( _gl, extensions, capabilities );\r\n\r\n\t\t\tstate = new WebGLState( _gl, extensions, capabilities );\r\n\t\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\r\n\t\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t\tinfo = new WebGLInfo( _gl );\r\n\t\t\tproperties = new WebGLProperties();\r\n\t\t\ttextures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );\r\n\t\t\tattributes = new WebGLAttributes( _gl );\r\n\t\t\tgeometries = new WebGLGeometries( _gl, attributes, info );\r\n\t\t\tobjects = new WebGLObjects( _gl, geometries, attributes, info );\r\n\t\t\tmorphtargets = new WebGLMorphtargets( _gl );\r\n\t\t\tprogramCache = new WebGLPrograms( _this, extensions, capabilities );\r\n\t\t\trenderLists = new WebGLRenderLists();\r\n\t\t\trenderStates = new WebGLRenderStates();\r\n\r\n\t\t\tbackground = new WebGLBackground( _this, state, objects, _premultipliedAlpha );\r\n\r\n\t\t\tbufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );\r\n\t\t\tindexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );\r\n\r\n\t\t\tinfo.programs = programCache.programs;\r\n\r\n\t\t\t_this.capabilities = capabilities;\r\n\t\t\t_this.extensions = extensions;\r\n\t\t\t_this.properties = properties;\r\n\t\t\t_this.renderLists = renderLists;\r\n\t\t\t_this.state = state;\r\n\t\t\t_this.info = info;\r\n\r\n\t\t}\r\n\r\n\t\tinitGLContext();\r\n\r\n\t\t// xr\r\n\r\n\t\tvar xr = ( typeof navigator !== 'undefined' && 'xr' in navigator ) ? new WebXRManager( _this, _gl ) : new WebVRManager( _this );\r\n\r\n\t\tthis.xr = xr;\r\n\r\n\t\t// Multiview\r\n\r\n\t\tvar multiview = new WebGLMultiview( _this, _gl );\r\n\r\n\t\t// shadow map\r\n\r\n\t\tvar shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );\r\n\r\n\t\tthis.shadowMap = shadowMap;\r\n\r\n\t\t// API\r\n\r\n\t\tthis.getContext = function () {\r\n\r\n\t\t\treturn _gl;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getContextAttributes = function () {\r\n\r\n\t\t\treturn _gl.getContextAttributes();\r\n\r\n\t\t};\r\n\r\n\t\tthis.forceContextLoss = function () {\r\n\r\n\t\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\r\n\t\t\tif ( extension ) { extension.loseContext(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.forceContextRestore = function () {\r\n\r\n\t\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\r\n\t\t\tif ( extension ) { extension.restoreContext(); }\r\n\r\n\t\t};\r\n\r\n\t\tthis.getPixelRatio = function () {\r\n\r\n\t\t\treturn _pixelRatio;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setPixelRatio = function ( value ) {\r\n\r\n\t\t\tif ( value === undefined ) { return; }\r\n\r\n\t\t\t_pixelRatio = value;\r\n\r\n\t\t\tthis.setSize( _width, _height, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getSize = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( _width, _height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setSize = function ( width, height, updateStyle ) {\r\n\r\n\t\t\tif ( xr.isPresenting() ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Can\\'t change size while VR device is presenting.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_width = width;\r\n\t\t\t_height = height;\r\n\r\n\t\t\t_canvas.width = Math.floor( width * _pixelRatio );\r\n\t\t\t_canvas.height = Math.floor( height * _pixelRatio );\r\n\r\n\t\t\tif ( updateStyle !== false ) {\r\n\r\n\t\t\t\t_canvas.style.width = width + 'px';\r\n\t\t\t\t_canvas.style.height = height + 'px';\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.setViewport( 0, 0, width, height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getDrawingBufferSize = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setDrawingBufferSize = function ( width, height, pixelRatio ) {\r\n\r\n\t\t\t_width = width;\r\n\t\t\t_height = height;\r\n\r\n\t\t\t_pixelRatio = pixelRatio;\r\n\r\n\t\t\t_canvas.width = Math.floor( width * pixelRatio );\r\n\t\t\t_canvas.height = Math.floor( height * pixelRatio );\r\n\r\n\t\t\tthis.setViewport( 0, 0, width, height );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getCurrentViewport = function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );\r\n\r\n\t\t\t\ttarget = new Vector4();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( _currentViewport );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getViewport = function ( target ) {\r\n\r\n\t\t\treturn target.copy( _viewport );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setViewport = function ( x, y, width, height ) {\r\n\r\n\t\t\tif ( x.isVector4 ) {\r\n\r\n\t\t\t\t_viewport.set( x.x, x.y, x.z, x.w );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_viewport.set( x, y, width, height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getScissor = function ( target ) {\r\n\r\n\t\t\treturn target.copy( _scissor );\r\n\r\n\t\t};\r\n\r\n\t\tthis.setScissor = function ( x, y, width, height ) {\r\n\r\n\t\t\tif ( x.isVector4 ) {\r\n\r\n\t\t\t\t_scissor.set( x.x, x.y, x.z, x.w );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_scissor.set( x, y, width, height );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getScissorTest = function () {\r\n\r\n\t\t\treturn _scissorTest;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setScissorTest = function ( boolean ) {\r\n\r\n\t\t\tstate.setScissorTest( _scissorTest = boolean );\r\n\r\n\t\t};\r\n\r\n\t\t// Clearing\r\n\r\n\t\tthis.getClearColor = function () {\r\n\r\n\t\t\treturn background.getClearColor();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setClearColor = function () {\r\n\r\n\t\t\tbackground.setClearColor.apply( background, arguments );\r\n\r\n\t\t};\r\n\r\n\t\tthis.getClearAlpha = function () {\r\n\r\n\t\t\treturn background.getClearAlpha();\r\n\r\n\t\t};\r\n\r\n\t\tthis.setClearAlpha = function () {\r\n\r\n\t\t\tbackground.setClearAlpha.apply( background, arguments );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clear = function ( color, depth, stencil ) {\r\n\r\n\t\t\tvar bits = 0;\r\n\r\n\t\t\tif ( color === undefined || color ) { bits |= 16384; }\r\n\t\t\tif ( depth === undefined || depth ) { bits |= 256; }\r\n\t\t\tif ( stencil === undefined || stencil ) { bits |= 1024; }\r\n\r\n\t\t\t_gl.clear( bits );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearColor = function () {\r\n\r\n\t\t\tthis.clear( true, false, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearDepth = function () {\r\n\r\n\t\t\tthis.clear( false, true, false );\r\n\r\n\t\t};\r\n\r\n\t\tthis.clearStencil = function () {\r\n\r\n\t\t\tthis.clear( false, false, true );\r\n\r\n\t\t};\r\n\r\n\t\t//\r\n\r\n\t\tthis.dispose = function () {\r\n\r\n\t\t\t_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );\r\n\t\t\t_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );\r\n\r\n\t\t\trenderLists.dispose();\r\n\t\t\trenderStates.dispose();\r\n\t\t\tproperties.dispose();\r\n\t\t\tobjects.dispose();\r\n\r\n\t\t\txr.dispose();\r\n\r\n\t\t\tanimation.stop();\r\n\r\n\t\t};\r\n\r\n\t\t// Events\r\n\r\n\t\tfunction onContextLost( event ) {\r\n\r\n\t\t\tevent.preventDefault();\r\n\r\n\t\t\tconsole.log( 'THREE.WebGLRenderer: Context Lost.' );\r\n\r\n\t\t\t_isContextLost = true;\r\n\r\n\t\t}\r\n\r\n\t\tfunction onContextRestore( /* event */ ) {\r\n\r\n\t\t\tconsole.log( 'THREE.WebGLRenderer: Context Restored.' );\r\n\r\n\t\t\t_isContextLost = false;\r\n\r\n\t\t\tinitGLContext();\r\n\r\n\t\t}\r\n\r\n\t\tfunction onMaterialDispose( event ) {\r\n\r\n\t\t\tvar material = event.target;\r\n\r\n\t\t\tmaterial.removeEventListener( 'dispose', onMaterialDispose );\r\n\r\n\t\t\tdeallocateMaterial( material );\r\n\r\n\t\t}\r\n\r\n\t\t// Buffer deallocation\r\n\r\n\t\tfunction deallocateMaterial( material ) {\r\n\r\n\t\t\treleaseMaterialProgramReference( material );\r\n\r\n\t\t\tproperties.remove( material );\r\n\r\n\t\t}\r\n\r\n\r\n\t\tfunction releaseMaterialProgramReference( material ) {\r\n\r\n\t\t\tvar programInfo = properties.get( material ).program;\r\n\r\n\t\t\tmaterial.program = undefined;\r\n\r\n\t\t\tif ( programInfo !== undefined ) {\r\n\r\n\t\t\t\tprogramCache.releaseProgram( programInfo );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Buffer rendering\r\n\r\n\t\tfunction renderObjectImmediate( object, program ) {\r\n\r\n\t\t\tobject.render( function ( object ) {\r\n\r\n\t\t\t\t_this.renderBufferImmediate( object, program );\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\tthis.renderBufferImmediate = function ( object, program ) {\r\n\r\n\t\t\tstate.initAttributes();\r\n\r\n\t\t\tvar buffers = properties.get( object );\r\n\r\n\t\t\tif ( object.hasPositions && ! buffers.position ) { buffers.position = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasNormals && ! buffers.normal ) { buffers.normal = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasUvs && ! buffers.uv ) { buffers.uv = _gl.createBuffer(); }\r\n\t\t\tif ( object.hasColors && ! buffers.color ) { buffers.color = _gl.createBuffer(); }\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tif ( object.hasPositions ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.position );\r\n\t\t\t\t_gl.bufferData( 34962, object.positionArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.position );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.position, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasNormals ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.normal );\r\n\t\t\t\t_gl.bufferData( 34962, object.normalArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.normal );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.normal, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasUvs ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.uv );\r\n\t\t\t\t_gl.bufferData( 34962, object.uvArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.uv );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.uv, 2, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.hasColors ) {\r\n\r\n\t\t\t\t_gl.bindBuffer( 34962, buffers.color );\r\n\t\t\t\t_gl.bufferData( 34962, object.colorArray, 35048 );\r\n\r\n\t\t\t\tstate.enableAttribute( programAttributes.color );\r\n\t\t\t\t_gl.vertexAttribPointer( programAttributes.color, 3, 5126, false, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.disableUnusedAttributes();\r\n\r\n\t\t\t_gl.drawArrays( 4, 0, object.count );\r\n\r\n\t\t\tobject.count = 0;\r\n\r\n\t\t};\r\n\r\n\t\tthis.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {\r\n\r\n\t\t\tvar frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );\r\n\r\n\t\t\tvar program = setProgram( camera, fog, material, object );\r\n\r\n\t\t\tstate.setMaterial( material, frontFaceCW );\r\n\r\n\t\t\tvar updateBuffers = false;\r\n\r\n\t\t\tif ( _currentGeometryProgram.geometry !== geometry.id ||\r\n\t\t\t\t_currentGeometryProgram.program !== program.id ||\r\n\t\t\t\t_currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {\r\n\r\n\t\t\t\t_currentGeometryProgram.geometry = geometry.id;\r\n\t\t\t\t_currentGeometryProgram.program = program.id;\r\n\t\t\t\t_currentGeometryProgram.wireframe = material.wireframe === true;\r\n\t\t\t\tupdateBuffers = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.morphTargets || material.morphNormals ) {\r\n\r\n\t\t\t\tmorphtargets.update( object, geometry, material, program );\r\n\r\n\t\t\t\tupdateBuffers = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar index = geometry.index;\r\n\t\t\tvar position = geometry.attributes.position;\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( index !== null && index.count === 0 ) { return; }\r\n\t\t\tif ( position === undefined || position.count === 0 ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar rangeFactor = 1;\r\n\r\n\t\t\tif ( material.wireframe === true ) {\r\n\r\n\t\t\t\tindex = geometries.getWireframeAttribute( geometry );\r\n\t\t\t\trangeFactor = 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attribute;\r\n\t\t\tvar renderer = bufferRenderer;\r\n\r\n\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\tattribute = attributes.get( index );\r\n\r\n\t\t\t\trenderer = indexedBufferRenderer;\r\n\t\t\t\trenderer.setIndex( attribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( updateBuffers ) {\r\n\r\n\t\t\t\tsetupVertexAttributes( object, geometry, material, program );\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\t_gl.bindBuffer( 34963, attribute.buffer );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar dataCount = ( index !== null ) ? index.count : position.count;\r\n\r\n\t\t\tvar rangeStart = geometry.drawRange.start * rangeFactor;\r\n\t\t\tvar rangeCount = geometry.drawRange.count * rangeFactor;\r\n\r\n\t\t\tvar groupStart = group !== null ? group.start * rangeFactor : 0;\r\n\t\t\tvar groupCount = group !== null ? group.count * rangeFactor : Infinity;\r\n\r\n\t\t\tvar drawStart = Math.max( rangeStart, groupStart );\r\n\t\t\tvar drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;\r\n\r\n\t\t\tvar drawCount = Math.max( 0, drawEnd - drawStart + 1 );\r\n\r\n\t\t\tif ( drawCount === 0 ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( object.isMesh ) {\r\n\r\n\t\t\t\tif ( material.wireframe === true ) {\r\n\r\n\t\t\t\t\tstate.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );\r\n\t\t\t\t\trenderer.setMode( 1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderer.setMode( 4 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isLine ) {\r\n\r\n\t\t\t\tvar lineWidth = material.linewidth;\r\n\r\n\t\t\t\tif ( lineWidth === undefined ) { lineWidth = 1; } // Not using Line*Material\r\n\r\n\t\t\t\tstate.setLineWidth( lineWidth * getTargetPixelRatio() );\r\n\r\n\t\t\t\tif ( object.isLineSegments ) {\r\n\r\n\t\t\t\t\trenderer.setMode( 1 );\r\n\r\n\t\t\t\t} else if ( object.isLineLoop ) {\r\n\r\n\t\t\t\t\trenderer.setMode( 2 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\trenderer.setMode( 3 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( object.isPoints ) {\r\n\r\n\t\t\t\trenderer.setMode( 0 );\r\n\r\n\t\t\t} else if ( object.isSprite ) {\r\n\r\n\t\t\t\trenderer.setMode( 4 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( object.isInstancedMesh ) {\r\n\r\n\t\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, object.count );\r\n\r\n\t\t\t} else if ( geometry.isInstancedBufferGeometry ) {\r\n\r\n\t\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, geometry.maxInstancedCount );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\trenderer.render( drawStart, drawCount );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tfunction setupVertexAttributes( object, geometry, material, program ) {\r\n\r\n\t\t\tif ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {\r\n\r\n\t\t\t\tif ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { return; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.initAttributes();\r\n\r\n\t\t\tvar geometryAttributes = geometry.attributes;\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tvar materialDefaultAttributeValues = material.defaultAttributeValues;\r\n\r\n\t\t\tfor ( var name in programAttributes ) {\r\n\r\n\t\t\t\tvar programAttribute = programAttributes[ name ];\r\n\r\n\t\t\t\tif ( programAttribute >= 0 ) {\r\n\r\n\t\t\t\t\tvar geometryAttribute = geometryAttributes[ name ];\r\n\r\n\t\t\t\t\tif ( geometryAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tvar normalized = geometryAttribute.normalized;\r\n\t\t\t\t\t\tvar size = geometryAttribute.itemSize;\r\n\r\n\t\t\t\t\t\tvar attribute = attributes.get( geometryAttribute );\r\n\r\n\t\t\t\t\t\t// TODO Attribute may not be available on context restore\r\n\r\n\t\t\t\t\t\tif ( attribute === undefined ) { continue; }\r\n\r\n\t\t\t\t\t\tvar buffer = attribute.buffer;\r\n\t\t\t\t\t\tvar type = attribute.type;\r\n\t\t\t\t\t\tvar bytesPerElement = attribute.bytesPerElement;\r\n\r\n\t\t\t\t\t\tif ( geometryAttribute.isInterleavedBufferAttribute ) {\r\n\r\n\t\t\t\t\t\t\tvar data = geometryAttribute.data;\r\n\t\t\t\t\t\t\tvar stride = data.stride;\r\n\t\t\t\t\t\t\tvar offset = geometryAttribute.offset;\r\n\r\n\t\t\t\t\t\t\tif ( data && data.isInstancedInterleavedBuffer ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );\r\n\r\n\t\t\t\t\t\t\t\tif ( geometry.maxInstancedCount === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tgeometry.maxInstancedCount = data.meshPerAttribute * data.count;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\t\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tif ( geometryAttribute.isInstancedBufferAttribute ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );\r\n\r\n\t\t\t\t\t\t\t\tif ( geometry.maxInstancedCount === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tgeometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\t\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else if ( name === 'instanceMatrix' ) {\r\n\r\n\t\t\t\t\t\tvar attribute = attributes.get( object.instanceMatrix );\r\n\r\n\t\t\t\t\t\t// TODO Attribute may not be available on context restore\r\n\r\n\t\t\t\t\t\tif ( attribute === undefined ) { continue; }\r\n\r\n\t\t\t\t\t\tvar buffer = attribute.buffer;\r\n\t\t\t\t\t\tvar type = attribute.type;\r\n\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 0, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 1, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 2, 1 );\r\n\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 3, 1 );\r\n\r\n\t\t\t\t\t\t_gl.bindBuffer( 34962, buffer );\r\n\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );\r\n\t\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );\r\n\r\n\t\t\t\t\t} else if ( materialDefaultAttributeValues !== undefined ) {\r\n\r\n\t\t\t\t\t\tvar value = materialDefaultAttributeValues[ name ];\r\n\r\n\t\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\t\tswitch ( value.length ) {\r\n\r\n\t\t\t\t\t\t\t\tcase 2:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib2fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase 3:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib3fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tcase 4:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib4fv( programAttribute, value );\r\n\t\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\t\t\t_gl.vertexAttrib1fv( programAttribute, value );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.disableUnusedAttributes();\r\n\r\n\t\t}\r\n\r\n\t\t// Compile\r\n\r\n\t\tthis.compile = function ( scene, camera ) {\r\n\r\n\t\t\tcurrentRenderState = renderStates.get( scene, camera );\r\n\t\t\tcurrentRenderState.init();\r\n\r\n\t\t\tscene.traverse( function ( object ) {\r\n\r\n\t\t\t\tif ( object.isLight ) {\r\n\r\n\t\t\t\t\tcurrentRenderState.pushLight( object );\r\n\r\n\t\t\t\t\tif ( object.castShadow ) {\r\n\r\n\t\t\t\t\t\tcurrentRenderState.pushShadow( object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tcurrentRenderState.setupLights( camera );\r\n\r\n\t\t\tscene.traverse( function ( object ) {\r\n\r\n\t\t\t\tif ( object.material ) {\r\n\r\n\t\t\t\t\tif ( Array.isArray( object.material ) ) {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < object.material.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tinitMaterial( object.material[ i ], scene.fog, object );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tinitMaterial( object.material, scene.fog, object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} );\r\n\r\n\t\t};\r\n\r\n\t\t// Animation Loop\r\n\r\n\t\tvar onAnimationFrameCallback = null;\r\n\r\n\t\tfunction onAnimationFrame( time ) {\r\n\r\n\t\t\tif ( xr.isPresenting() ) { return; }\r\n\t\t\tif ( onAnimationFrameCallback ) { onAnimationFrameCallback( time ); }\r\n\r\n\t\t}\r\n\r\n\t\tvar animation = new WebGLAnimation();\r\n\t\tanimation.setAnimationLoop( onAnimationFrame );\r\n\r\n\t\tif ( typeof window !== 'undefined' ) { animation.setContext( window ); }\r\n\r\n\t\tthis.setAnimationLoop = function ( callback ) {\r\n\r\n\t\t\tonAnimationFrameCallback = callback;\r\n\t\t\txr.setAnimationLoop( callback );\r\n\r\n\t\t\tanimation.start();\r\n\r\n\t\t};\r\n\r\n\t\t// Rendering\r\n\r\n\t\tthis.render = function ( scene, camera ) {\r\n\r\n\t\t\tvar renderTarget, forceClear;\r\n\r\n\t\t\tif ( arguments[ 2 ] !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );\r\n\t\t\t\trenderTarget = arguments[ 2 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( arguments[ 3 ] !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );\r\n\t\t\t\tforceClear = arguments[ 3 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ! ( camera && camera.isCamera ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _isContextLost ) { return; }\r\n\r\n\t\t\t// reset caching for this frame\r\n\r\n\t\t\t_currentGeometryProgram.geometry = null;\r\n\t\t\t_currentGeometryProgram.program = null;\r\n\t\t\t_currentGeometryProgram.wireframe = false;\r\n\t\t\t_currentMaterialId = - 1;\r\n\t\t\t_currentCamera = null;\r\n\r\n\t\t\t// update scene graph\r\n\r\n\t\t\tif ( scene.autoUpdate === true ) { scene.updateMatrixWorld(); }\r\n\r\n\t\t\t// update camera matrices and frustum\r\n\r\n\t\t\tif ( camera.parent === null ) { camera.updateMatrixWorld(); }\r\n\r\n\t\t\tif ( xr.enabled && xr.isPresenting() ) {\r\n\r\n\t\t\t\tcamera = xr.getCamera( camera );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tcurrentRenderState = renderStates.get( scene, camera );\r\n\t\t\tcurrentRenderState.init();\r\n\r\n\t\t\tscene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );\r\n\r\n\t\t\t_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\r\n\t\t\t_frustum.setFromMatrix( _projScreenMatrix );\r\n\r\n\t\t\t_localClippingEnabled = this.localClippingEnabled;\r\n\t\t\t_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );\r\n\r\n\t\t\tcurrentRenderList = renderLists.get( scene, camera );\r\n\t\t\tcurrentRenderList.init();\r\n\r\n\t\t\tprojectObject( scene, camera, 0, _this.sortObjects );\r\n\r\n\t\t\tif ( _this.sortObjects === true ) {\r\n\r\n\t\t\t\tcurrentRenderList.sort();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( _clippingEnabled ) { _clipping.beginShadows(); }\r\n\r\n\t\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\r\n\r\n\t\t\tshadowMap.render( shadowsArray, scene, camera );\r\n\r\n\t\t\tcurrentRenderState.setupLights( camera );\r\n\r\n\t\t\tif ( _clippingEnabled ) { _clipping.endShadows(); }\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( this.info.autoReset ) { this.info.reset(); }\r\n\r\n\t\t\tif ( renderTarget !== undefined ) {\r\n\r\n\t\t\t\tthis.setRenderTarget( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( xr.enabled && multiview.isAvailable() ) {\r\n\r\n\t\t\t\tmultiview.attachCamera( camera );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tbackground.render( currentRenderList, scene, camera, forceClear );\r\n\r\n\t\t\t// render scene\r\n\r\n\t\t\tvar opaqueObjects = currentRenderList.opaque;\r\n\t\t\tvar transparentObjects = currentRenderList.transparent;\r\n\r\n\t\t\tif ( scene.overrideMaterial ) {\r\n\r\n\t\t\t\tvar overrideMaterial = scene.overrideMaterial;\r\n\r\n\t\t\t\tif ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera, overrideMaterial ); }\r\n\t\t\t\tif ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera, overrideMaterial ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// opaque pass (front-to-back order)\r\n\r\n\t\t\t\tif ( opaqueObjects.length ) { renderObjects( opaqueObjects, scene, camera ); }\r\n\r\n\t\t\t\t// transparent pass (back-to-front order)\r\n\r\n\t\t\t\tif ( transparentObjects.length ) { renderObjects( transparentObjects, scene, camera ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tscene.onAfterRender( _this, scene, camera );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tif ( _currentRenderTarget !== null ) {\r\n\r\n\t\t\t\t// Generate mipmap if we're using any kind of mipmap filtering\r\n\r\n\t\t\t\ttextures.updateRenderTargetMipmap( _currentRenderTarget );\r\n\r\n\t\t\t\t// resolve multisample renderbuffers to a single-sample texture if necessary\r\n\r\n\t\t\t\ttextures.updateMultisampleRenderTarget( _currentRenderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Ensure depth buffer writing is enabled so it can be cleared on next render\r\n\r\n\t\t\tstate.buffers.depth.setTest( true );\r\n\t\t\tstate.buffers.depth.setMask( true );\r\n\t\t\tstate.buffers.color.setMask( true );\r\n\r\n\t\t\tstate.setPolygonOffset( false );\r\n\r\n\t\t\tif ( xr.enabled ) {\r\n\r\n\t\t\t\tif ( multiview.isAvailable() ) {\r\n\r\n\t\t\t\t\tmultiview.detachCamera( camera );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\txr.submitFrame();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// _gl.finish();\r\n\r\n\t\t\tcurrentRenderList = null;\r\n\t\t\tcurrentRenderState = null;\r\n\r\n\t\t};\r\n\r\n\t\tfunction projectObject( object, camera, groupOrder, sortObjects ) {\r\n\r\n\t\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\t\tvar visible = object.layers.test( camera.layers );\r\n\r\n\t\t\tif ( visible ) {\r\n\r\n\t\t\t\tif ( object.isGroup ) {\r\n\r\n\t\t\t\t\tgroupOrder = object.renderOrder;\r\n\r\n\t\t\t\t} else if ( object.isLOD ) {\r\n\r\n\t\t\t\t\tif ( object.autoUpdate === true ) { object.update( camera ); }\r\n\r\n\t\t\t\t} else if ( object.isLight ) {\r\n\r\n\t\t\t\t\tcurrentRenderState.pushLight( object );\r\n\r\n\t\t\t\t\tif ( object.castShadow ) {\r\n\r\n\t\t\t\t\t\tcurrentRenderState.pushShadow( object );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( object.isSprite ) {\r\n\r\n\t\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {\r\n\r\n\t\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar geometry = objects.update( object );\r\n\t\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\t\tif ( material.visible ) {\r\n\r\n\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( object.isImmediateRenderObject ) {\r\n\r\n\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcurrentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t} else if ( object.isMesh || object.isLine || object.isPoints ) {\r\n\r\n\t\t\t\t\tif ( object.isSkinnedMesh ) {\r\n\r\n\t\t\t\t\t\t// update skeleton only once in a frame\r\n\r\n\t\t\t\t\t\tif ( object.skeleton.frame !== info.render.frame ) {\r\n\r\n\t\t\t\t\t\t\tobject.skeleton.update();\r\n\t\t\t\t\t\t\tobject.skeleton.frame = info.render.frame;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {\r\n\r\n\t\t\t\t\t\tif ( sortObjects ) {\r\n\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\r\n\t\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar geometry = objects.update( object );\r\n\t\t\t\t\t\tvar material = object.material;\r\n\r\n\t\t\t\t\t\tif ( Array.isArray( material ) ) {\r\n\r\n\t\t\t\t\t\t\tvar groups = geometry.groups;\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar group = groups[ i ];\r\n\t\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\r\n\r\n\t\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\r\n\r\n\t\t\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else if ( material.visible ) {\r\n\r\n\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tprojectObject( children[ i ], camera, groupOrder, sortObjects );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObjects( renderList, scene, camera, overrideMaterial ) {\r\n\r\n\t\t\tfor ( var i = 0, l = renderList.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar renderItem = renderList[ i ];\r\n\r\n\t\t\t\tvar object = renderItem.object;\r\n\t\t\t\tvar geometry = renderItem.geometry;\r\n\t\t\t\tvar material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;\r\n\t\t\t\tvar group = renderItem.group;\r\n\r\n\t\t\t\tif ( camera.isArrayCamera ) {\r\n\r\n\t\t\t\t\t_currentArrayCamera = camera;\r\n\r\n\t\t\t\t\tif ( xr.enabled && multiview.isAvailable() ) {\r\n\r\n\t\t\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tvar cameras = camera.cameras;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = cameras.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar camera2 = cameras[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( object.layers.test( camera2.layers ) ) {\r\n\r\n\t\t\t\t\t\t\t\tstate.viewport( _currentViewport.copy( camera2.viewport ) );\r\n\r\n\t\t\t\t\t\t\t\tcurrentRenderState.setupLights( camera2 );\r\n\r\n\t\t\t\t\t\t\t\trenderObject( object, scene, camera2, geometry, material, group );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t_currentArrayCamera = null;\r\n\r\n\t\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction renderObject( object, scene, camera, geometry, material, group ) {\r\n\r\n\t\t\tobject.onBeforeRender( _this, scene, camera, geometry, material, group );\r\n\t\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\r\n\r\n\t\t\tobject.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );\r\n\t\t\tobject.normalMatrix.getNormalMatrix( object.modelViewMatrix );\r\n\r\n\t\t\tif ( object.isImmediateRenderObject ) {\r\n\r\n\t\t\t\tvar program = setProgram( camera, scene.fog, material, object );\r\n\r\n\t\t\t\tstate.setMaterial( material );\r\n\r\n\t\t\t\t_currentGeometryProgram.geometry = null;\r\n\t\t\t\t_currentGeometryProgram.program = null;\r\n\t\t\t\t_currentGeometryProgram.wireframe = false;\r\n\r\n\t\t\t\trenderObjectImmediate( object, program );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_this.renderBufferDirect( camera, scene.fog, geometry, material, object, group );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.onAfterRender( _this, scene, camera, geometry, material, group );\r\n\t\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\r\n\r\n\t\t}\r\n\r\n\t\tfunction initMaterial( material, fog, object ) {\r\n\r\n\t\t\tvar materialProperties = properties.get( material );\r\n\r\n\t\t\tvar lights = currentRenderState.state.lights;\r\n\t\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\r\n\r\n\t\t\tvar lightsStateVersion = lights.state.version;\r\n\r\n\t\t\tvar parameters = programCache.getParameters(\r\n\t\t\t\tmaterial, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object );\r\n\r\n\t\t\tvar programCacheKey = programCache.getProgramCacheKey( material, parameters );\r\n\r\n\t\t\tvar program = materialProperties.program;\r\n\t\t\tvar programChange = true;\r\n\r\n\t\t\tif ( program === undefined ) {\r\n\r\n\t\t\t\t// new material\r\n\t\t\t\tmaterial.addEventListener( 'dispose', onMaterialDispose );\r\n\r\n\t\t\t} else if ( program.cacheKey !== programCacheKey ) {\r\n\r\n\t\t\t\t// changed glsl or parameters\r\n\t\t\t\treleaseMaterialProgramReference( material );\r\n\r\n\t\t\t} else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {\r\n\r\n\t\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\r\n\r\n\t\t\t\tprogramChange = false;\r\n\r\n\t\t\t} else if ( parameters.shaderID !== undefined ) {\r\n\r\n\t\t\t\t// same glsl and uniform list\r\n\t\t\t\treturn;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// only rebuild uniform list\r\n\t\t\t\tprogramChange = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( programChange ) {\r\n\r\n\t\t\t\tif ( parameters.shaderID ) {\r\n\r\n\t\t\t\t\tvar shader = ShaderLib[ parameters.shaderID ];\r\n\r\n\t\t\t\t\tmaterialProperties.shader = {\r\n\t\t\t\t\t\tname: material.type,\r\n\t\t\t\t\t\tuniforms: cloneUniforms( shader.uniforms ),\r\n\t\t\t\t\t\tvertexShader: shader.vertexShader,\r\n\t\t\t\t\t\tfragmentShader: shader.fragmentShader\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tmaterialProperties.shader = {\r\n\t\t\t\t\t\tname: material.type,\r\n\t\t\t\t\t\tuniforms: material.uniforms,\r\n\t\t\t\t\t\tvertexShader: material.vertexShader,\r\n\t\t\t\t\t\tfragmentShader: material.fragmentShader\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmaterial.onBeforeCompile( materialProperties.shader, _this );\r\n\r\n\t\t\t\t// Computing cache key again as onBeforeCompile may have changed the shaders\r\n\t\t\t\tprogramCacheKey = programCache.getProgramCacheKey( material, parameters );\r\n\r\n\t\t\t\tprogram = programCache.acquireProgram( material, materialProperties.shader, parameters, programCacheKey );\r\n\r\n\t\t\t\tmaterialProperties.program = program;\r\n\t\t\t\tmaterial.program = program;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar programAttributes = program.getAttributes();\r\n\r\n\t\t\tif ( material.morphTargets ) {\r\n\r\n\t\t\t\tmaterial.numSupportedMorphTargets = 0;\r\n\r\n\t\t\t\tfor ( var i = 0; i < _this.maxMorphTargets; i ++ ) {\r\n\r\n\t\t\t\t\tif ( programAttributes[ 'morphTarget' + i ] >= 0 ) {\r\n\r\n\t\t\t\t\t\tmaterial.numSupportedMorphTargets ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.morphNormals ) {\r\n\r\n\t\t\t\tmaterial.numSupportedMorphNormals = 0;\r\n\r\n\t\t\t\tfor ( var i = 0; i < _this.maxMorphNormals; i ++ ) {\r\n\r\n\t\t\t\t\tif ( programAttributes[ 'morphNormal' + i ] >= 0 ) {\r\n\r\n\t\t\t\t\t\tmaterial.numSupportedMorphNormals ++;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar uniforms = materialProperties.shader.uniforms;\r\n\r\n\t\t\tif ( ! material.isShaderMaterial &&\r\n\t\t\t\t! material.isRawShaderMaterial ||\r\n\t\t\t\tmaterial.clipping === true ) {\r\n\r\n\t\t\t\tmaterialProperties.numClippingPlanes = _clipping.numPlanes;\r\n\t\t\t\tmaterialProperties.numIntersection = _clipping.numIntersection;\r\n\t\t\t\tuniforms.clippingPlanes = _clipping.uniform;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterialProperties.fog = fog;\r\n\r\n\t\t\t// store the light setup it was created for\r\n\r\n\t\t\tmaterialProperties.needsLights = materialNeedsLights( material );\r\n\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\r\n\r\n\t\t\tif ( materialProperties.needsLights ) {\r\n\r\n\t\t\t\t// wire up the material to this renderer's lighting state\r\n\r\n\t\t\t\tuniforms.ambientLightColor.value = lights.state.ambient;\r\n\t\t\t\tuniforms.lightProbe.value = lights.state.probe;\r\n\t\t\t\tuniforms.directionalLights.value = lights.state.directional;\r\n\t\t\t\tuniforms.spotLights.value = lights.state.spot;\r\n\t\t\t\tuniforms.rectAreaLights.value = lights.state.rectArea;\r\n\t\t\t\tuniforms.pointLights.value = lights.state.point;\r\n\t\t\t\tuniforms.hemisphereLights.value = lights.state.hemi;\r\n\r\n\t\t\t\tuniforms.directionalShadowMap.value = lights.state.directionalShadowMap;\r\n\t\t\t\tuniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;\r\n\t\t\t\tuniforms.spotShadowMap.value = lights.state.spotShadowMap;\r\n\t\t\t\tuniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;\r\n\t\t\t\tuniforms.pointShadowMap.value = lights.state.pointShadowMap;\r\n\t\t\t\tuniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;\r\n\t\t\t\t// TODO (abelnation): add area lights shadow info to uniforms\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar progUniforms = materialProperties.program.getUniforms(),\r\n\t\t\t\tuniformsList =\r\n\t\t\t\t\tWebGLUniforms.seqWithValue( progUniforms.seq, uniforms );\r\n\r\n\t\t\tmaterialProperties.uniformsList = uniformsList;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setProgram( camera, fog, material, object ) {\r\n\r\n\t\t\ttextures.resetTextureUnits();\r\n\r\n\t\t\tvar materialProperties = properties.get( material );\r\n\t\t\tvar lights = currentRenderState.state.lights;\r\n\r\n\t\t\tif ( _clippingEnabled ) {\r\n\r\n\t\t\t\tif ( _localClippingEnabled || camera !== _currentCamera ) {\r\n\r\n\t\t\t\t\tvar useCache =\r\n\t\t\t\t\t\tcamera === _currentCamera &&\r\n\t\t\t\t\t\tmaterial.id === _currentMaterialId;\r\n\r\n\t\t\t\t\t// we might want to call this function with some ClippingGroup\r\n\t\t\t\t\t// object instead of the material, once it becomes feasible\r\n\t\t\t\t\t// (#8465, #8379)\r\n\t\t\t\t\t_clipping.setState(\r\n\t\t\t\t\t\tmaterial.clippingPlanes, material.clipIntersection, material.clipShadows,\r\n\t\t\t\t\t\tcamera, materialProperties, useCache );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.version === materialProperties.__version ) {\r\n\r\n\t\t\t\tif ( materialProperties.program === undefined ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( material.fog && materialProperties.fog !== fog ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t} else if ( materialProperties.numClippingPlanes !== undefined &&\r\n\t\t\t\t\t( materialProperties.numClippingPlanes !== _clipping.numPlanes ||\r\n\t\t\t\t\tmaterialProperties.numIntersection !== _clipping.numIntersection ) ) {\r\n\r\n\t\t\t\t\tmaterial.needsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.version !== materialProperties.__version ) {\r\n\r\n\t\t\t\tinitMaterial( material, fog, object );\r\n\t\t\t\tmaterialProperties.__version = material.version;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar refreshProgram = false;\r\n\t\t\tvar refreshMaterial = false;\r\n\t\t\tvar refreshLights = false;\r\n\r\n\t\t\tvar program = materialProperties.program,\r\n\t\t\t\tp_uniforms = program.getUniforms(),\r\n\t\t\t\tm_uniforms = materialProperties.shader.uniforms;\r\n\r\n\t\t\tif ( state.useProgram( program.program ) ) {\r\n\r\n\t\t\t\trefreshProgram = true;\r\n\t\t\t\trefreshMaterial = true;\r\n\t\t\t\trefreshLights = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.id !== _currentMaterialId ) {\r\n\r\n\t\t\t\t_currentMaterialId = material.id;\r\n\r\n\t\t\t\trefreshMaterial = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshProgram || _currentCamera !== camera ) {\r\n\r\n\t\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\t\tmultiview.updateCameraProjectionMatricesUniform( camera, p_uniforms );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( capabilities.logarithmicDepthBuffer ) {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'logDepthBufFC',\r\n\t\t\t\t\t\t2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( _currentCamera !== camera ) {\r\n\r\n\t\t\t\t\t_currentCamera = camera;\r\n\r\n\t\t\t\t\t// lighting uniforms depend on the camera so enforce an update\r\n\t\t\t\t\t// now, in case this material supports lights - or later, when\r\n\t\t\t\t\t// the next material that does gets activated:\r\n\r\n\t\t\t\t\trefreshMaterial = true;\t\t// set to true on material change\r\n\t\t\t\t\trefreshLights = true;\t\t// remains set until update done\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// load material specific uniforms\r\n\t\t\t\t// (shader material also gets them for the sake of genericity)\r\n\r\n\t\t\t\tif ( material.isShaderMaterial ||\r\n\t\t\t\t\tmaterial.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.envMap ) {\r\n\r\n\t\t\t\t\tvar uCamPos = p_uniforms.map.cameraPosition;\r\n\r\n\t\t\t\t\tif ( uCamPos !== undefined ) {\r\n\r\n\t\t\t\t\t\tuCamPos.setValue( _gl,\r\n\t\t\t\t\t\t\t_vector3.setFromMatrixPosition( camera.matrixWorld ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshLambertMaterial ||\r\n\t\t\t\t\tmaterial.isMeshBasicMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.isShaderMaterial ) {\r\n\r\n\t\t\t\t\tp_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshPhongMaterial ||\r\n\t\t\t\t\tmaterial.isMeshToonMaterial ||\r\n\t\t\t\t\tmaterial.isMeshLambertMaterial ||\r\n\t\t\t\t\tmaterial.isMeshBasicMaterial ||\r\n\t\t\t\t\tmaterial.isMeshStandardMaterial ||\r\n\t\t\t\t\tmaterial.isShaderMaterial ||\r\n\t\t\t\t\tmaterial.skinning ) {\r\n\r\n\t\t\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\t\t\tmultiview.updateCameraViewMatricesUniform( camera, p_uniforms );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// skinning uniforms must be set even if material didn't change\r\n\t\t\t// auto-setting of texture unit for bone texture must go before other textures\r\n\t\t\t// not sure why, but otherwise weird things happen\r\n\r\n\t\t\tif ( material.skinning ) {\r\n\r\n\t\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrix' );\r\n\t\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );\r\n\r\n\t\t\t\tvar skeleton = object.skeleton;\r\n\r\n\t\t\t\tif ( skeleton ) {\r\n\r\n\t\t\t\t\tvar bones = skeleton.bones;\r\n\r\n\t\t\t\t\tif ( capabilities.floatVertexTextures ) {\r\n\r\n\t\t\t\t\t\tif ( skeleton.boneTexture === undefined ) {\r\n\r\n\t\t\t\t\t\t\t// layout (1 matrix = 4 pixels)\r\n\t\t\t\t\t\t\t// RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)\r\n\t\t\t\t\t\t\t// with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)\r\n\t\t\t\t\t\t\t// 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)\r\n\t\t\t\t\t\t\t// 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)\r\n\t\t\t\t\t\t\t// 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)\r\n\r\n\r\n\t\t\t\t\t\t\tvar size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix\r\n\t\t\t\t\t\t\tsize = _Math.ceilPowerOfTwo( size );\r\n\t\t\t\t\t\t\tsize = Math.max( size, 4 );\r\n\r\n\t\t\t\t\t\t\tvar boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel\r\n\t\t\t\t\t\t\tboneMatrices.set( skeleton.boneMatrices ); // copy current values\r\n\r\n\t\t\t\t\t\t\tvar boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );\r\n\r\n\t\t\t\t\t\t\tskeleton.boneMatrices = boneMatrices;\r\n\t\t\t\t\t\t\tskeleton.boneTexture = boneTexture;\r\n\t\t\t\t\t\t\tskeleton.boneTextureSize = size;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );\r\n\t\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tp_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {\r\n\r\n\t\t\t\tmaterialProperties.receiveShadow = object.receiveShadow;\r\n\t\t\t\tp_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( refreshMaterial ) {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );\r\n\t\t\t\tp_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );\r\n\r\n\t\t\t\tif ( materialProperties.needsLights ) {\r\n\r\n\t\t\t\t\t// the current material requires lighting info\r\n\r\n\t\t\t\t\t// note: all lighting uniforms are always set correctly\r\n\t\t\t\t\t// they simply reference the renderer's state for their\r\n\t\t\t\t\t// values\r\n\t\t\t\t\t//\r\n\t\t\t\t\t// use the current material's .needsUpdate flags to set\r\n\t\t\t\t\t// the GL state when required\r\n\r\n\t\t\t\t\tmarkUniformsLightsNeedsUpdate( m_uniforms, refreshLights );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// refresh uniforms common to several materials\r\n\r\n\t\t\t\tif ( fog && material.fog ) {\r\n\r\n\t\t\t\t\trefreshUniformsFog( m_uniforms, fog );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.isMeshBasicMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshLambertMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsLambert( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshToonMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsToon( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshPhongMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsPhong( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshStandardMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t\tif ( material.isMeshPhysicalMaterial ) {\r\n\r\n\t\t\t\t\t\trefreshUniformsPhysical( m_uniforms, material );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\trefreshUniformsStandard( m_uniforms, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( material.isMeshMatcapMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t\trefreshUniformsMatcap( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshDepthMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsDepth( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshDistanceMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsDistance( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isMeshNormalMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\t\t\t\t\trefreshUniformsNormal( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isLineBasicMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsLine( m_uniforms, material );\r\n\r\n\t\t\t\t\tif ( material.isLineDashedMaterial ) {\r\n\r\n\t\t\t\t\t\trefreshUniformsDash( m_uniforms, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( material.isPointsMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsPoints( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isSpriteMaterial ) {\r\n\r\n\t\t\t\t\trefreshUniformsSprites( m_uniforms, material );\r\n\r\n\t\t\t\t} else if ( material.isShadowMaterial ) {\r\n\r\n\t\t\t\t\tm_uniforms.color.value.copy( material.color );\r\n\t\t\t\t\tm_uniforms.opacity.value = material.opacity;\r\n\r\n\t\t\t\t} else if ( material.envMap ) {\r\n\r\n\t\t\t\t\trefreshUniformsCommon( m_uniforms, material );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// RectAreaLight Texture\r\n\t\t\t\t// TODO (mrdoob): Find a nicer implementation\r\n\r\n\t\t\t\tif ( m_uniforms.ltc_1 !== undefined ) { m_uniforms.ltc_1.value = UniformsLib.LTC_1; }\r\n\t\t\t\tif ( m_uniforms.ltc_2 !== undefined ) { m_uniforms.ltc_2.value = UniformsLib.LTC_2; }\r\n\r\n\t\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\r\n\r\n\t\t\t\tif ( material.isShaderMaterial ) {\r\n\r\n\t\t\t\t\tmaterial.uniformsNeedUpdate = false; // #15581\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {\r\n\r\n\t\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\r\n\t\t\t\tmaterial.uniformsNeedUpdate = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.isSpriteMaterial ) {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'center', object.center );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// common matrices\r\n\r\n\t\t\tif ( program.numMultiviewViews > 0 ) {\r\n\r\n\t\t\t\tmultiview.updateObjectMatricesUniforms( object, camera, p_uniforms );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );\r\n\t\t\t\tp_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );\r\n\r\n\t\t\treturn program;\r\n\r\n\t\t}\r\n\r\n\t\t// Uniforms (refresh uniforms objects)\r\n\r\n\t\tfunction refreshUniformsCommon( uniforms, material ) {\r\n\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\r\n\t\t\tif ( material.color ) {\r\n\r\n\t\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissive ) {\r\n\r\n\t\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.specularMap ) {\r\n\r\n\t\t\t\tuniforms.specularMap.value = material.specularMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.envMap ) {\r\n\r\n\t\t\t\tuniforms.envMap.value = material.envMap;\r\n\r\n\t\t\t\t// don't flip CubeTexture envMaps, flip everything else:\r\n\t\t\t\t// WebGLRenderTargetCube will be flipped for backwards compatibility\r\n\t\t\t\t// WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture\r\n\t\t\t\t// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future\r\n\t\t\t\tuniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;\r\n\r\n\t\t\t\tuniforms.reflectivity.value = material.reflectivity;\r\n\t\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\r\n\r\n\t\t\t\tuniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.lightMap ) {\r\n\r\n\t\t\t\tuniforms.lightMap.value = material.lightMap;\r\n\t\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.aoMap ) {\r\n\r\n\t\t\t\tuniforms.aoMap.value = material.aoMap;\r\n\t\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. specular map\r\n\t\t\t// 3. normal map\r\n\t\t\t// 4. bump map\r\n\t\t\t// 5. alpha map\r\n\t\t\t// 6. emissive map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.specularMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.specularMap;\r\n\r\n\t\t\t} else if ( material.displacementMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.displacementMap;\r\n\r\n\t\t\t} else if ( material.normalMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.normalMap;\r\n\r\n\t\t\t} else if ( material.bumpMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.bumpMap;\r\n\r\n\t\t\t} else if ( material.roughnessMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.roughnessMap;\r\n\r\n\t\t\t} else if ( material.metalnessMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.metalnessMap;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t} else if ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\t// backwards compatibility\r\n\t\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tuvScaleMap = uvScaleMap.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities for uv2\r\n\t\t\t// 1. ao map\r\n\t\t\t// 2. light map\r\n\r\n\t\t\tvar uv2ScaleMap;\r\n\r\n\t\t\tif ( material.aoMap ) {\r\n\r\n\t\t\t\tuv2ScaleMap = material.aoMap;\r\n\r\n\t\t\t} else if ( material.lightMap ) {\r\n\r\n\t\t\t\tuv2ScaleMap = material.lightMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uv2ScaleMap !== undefined ) {\r\n\r\n\t\t\t\t// backwards compatibility\r\n\t\t\t\tif ( uv2ScaleMap.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tuv2ScaleMap = uv2ScaleMap.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uv2ScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuv2ScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsLine( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDash( uniforms, material ) {\r\n\r\n\t\t\tuniforms.dashSize.value = material.dashSize;\r\n\t\t\tuniforms.totalSize.value = material.dashSize + material.gapSize;\r\n\t\t\tuniforms.scale.value = material.scale;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPoints( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\t\t\tuniforms.size.value = material.size * _pixelRatio;\r\n\t\t\tuniforms.scale.value = _height * 0.5;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. alpha map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsSprites( uniforms, material ) {\r\n\r\n\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\tuniforms.opacity.value = material.opacity;\r\n\t\t\tuniforms.rotation.value = material.rotation;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.alphaMap ) {\r\n\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t// 1. color map\r\n\t\t\t// 2. alpha map\r\n\r\n\t\t\tvar uvScaleMap;\r\n\r\n\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsFog( uniforms, fog ) {\r\n\r\n\t\t\tuniforms.fogColor.value.copy( fog.color );\r\n\r\n\t\t\tif ( fog.isFog ) {\r\n\r\n\t\t\t\tuniforms.fogNear.value = fog.near;\r\n\t\t\t\tuniforms.fogFar.value = fog.far;\r\n\r\n\t\t\t} else if ( fog.isFogExp2 ) {\r\n\r\n\t\t\t\tuniforms.fogDensity.value = fog.density;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsLambert( uniforms, material ) {\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPhong( uniforms, material ) {\r\n\r\n\t\t\tuniforms.specular.value.copy( material.specular );\r\n\t\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsToon( uniforms, material ) {\r\n\r\n\t\t\tuniforms.specular.value.copy( material.specular );\r\n\t\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\r\n\r\n\t\t\tif ( material.gradientMap ) {\r\n\r\n\t\t\t\tuniforms.gradientMap.value = material.gradientMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsStandard( uniforms, material ) {\r\n\r\n\t\t\tuniforms.roughness.value = material.roughness;\r\n\t\t\tuniforms.metalness.value = material.metalness;\r\n\r\n\t\t\tif ( material.roughnessMap ) {\r\n\r\n\t\t\t\tuniforms.roughnessMap.value = material.roughnessMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.metalnessMap ) {\r\n\r\n\t\t\t\tuniforms.metalnessMap.value = material.metalnessMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.emissiveMap ) {\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.envMap ) {\r\n\r\n\t\t\t\t//uniforms.envMap.value = material.envMap; // part of uniforms common\r\n\t\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsPhysical( uniforms, material ) {\r\n\r\n\t\t\trefreshUniformsStandard( uniforms, material );\r\n\r\n\t\t\tuniforms.reflectivity.value = material.reflectivity; // also part of uniforms common\r\n\r\n\t\t\tuniforms.clearcoat.value = material.clearcoat;\r\n\t\t\tuniforms.clearcoatRoughness.value = material.clearcoatRoughness;\r\n\t\t\tif ( material.sheen ) { uniforms.sheen.value.copy( material.sheen ); }\r\n\r\n\t\t\tif ( material.clearcoatNormalMap ) {\r\n\r\n\t\t\t\tuniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );\r\n\t\t\t\tuniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;\r\n\r\n\t\t\t\tif ( material.side === BackSide ) {\r\n\r\n\t\t\t\t\tuniforms.clearcoatNormalScale.value.negate();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.transparency.value = material.transparency;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsMatcap( uniforms, material ) {\r\n\r\n\t\t\tif ( material.matcap ) {\r\n\r\n\t\t\t\tuniforms.matcap.value = material.matcap;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDepth( uniforms, material ) {\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsDistance( uniforms, material ) {\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tuniforms.referencePosition.value.copy( material.referencePosition );\r\n\t\t\tuniforms.nearDistance.value = material.nearDistance;\r\n\t\t\tuniforms.farDistance.value = material.farDistance;\r\n\r\n\t\t}\r\n\r\n\t\tfunction refreshUniformsNormal( uniforms, material ) {\r\n\r\n\t\t\tif ( material.bumpMap ) {\r\n\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.bumpScale.value = material.bumpScale;\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.bumpScale.value *= - 1; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.normalMap ) {\r\n\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\t\t\t\tuniforms.normalScale.value.copy( material.normalScale );\r\n\t\t\t\tif ( material.side === BackSide ) { uniforms.normalScale.value.negate(); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( material.displacementMap ) {\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// If uniforms are marked as clean, they don't need to be loaded to the GPU.\r\n\r\n\t\tfunction markUniformsLightsNeedsUpdate( uniforms, value ) {\r\n\r\n\t\t\tuniforms.ambientLightColor.needsUpdate = value;\r\n\t\t\tuniforms.lightProbe.needsUpdate = value;\r\n\r\n\t\t\tuniforms.directionalLights.needsUpdate = value;\r\n\t\t\tuniforms.pointLights.needsUpdate = value;\r\n\t\t\tuniforms.spotLights.needsUpdate = value;\r\n\t\t\tuniforms.rectAreaLights.needsUpdate = value;\r\n\t\t\tuniforms.hemisphereLights.needsUpdate = value;\r\n\r\n\t\t}\r\n\r\n\t\tfunction materialNeedsLights( material ) {\r\n\r\n\t\t\treturn material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||\r\n\t\t\t\tmaterial.isMeshStandardMaterial || material.isShadowMaterial ||\r\n\t\t\t\t( material.isShaderMaterial && material.lights === true );\r\n\r\n\t\t}\r\n\r\n\t\t// this.setTexture2D = setTexture2D;\r\n\t\tthis.setTexture2D = ( function () {\r\n\r\n\t\t\tvar warned = false;\r\n\r\n\t\t\t// backwards compatibility: peel texture.texture\r\n\t\t\treturn function setTexture2D( texture, slot ) {\r\n\r\n\t\t\t\tif ( texture && texture.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\tif ( ! warned ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( \"THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\r\n\t\t\t\t\t\twarned = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture = texture.texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttextures.setTexture2D( texture, slot );\r\n\r\n\t\t\t};\r\n\r\n\t\t}() );\r\n\r\n\t\t//\r\n\t\tthis.setFramebuffer = function ( value ) {\r\n\r\n\t\t\tif ( _framebuffer !== value && _currentRenderTarget === null ) { _gl.bindFramebuffer( 36160, value ); }\r\n\r\n\t\t\t_framebuffer = value;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getActiveCubeFace = function () {\r\n\r\n\t\t\treturn _currentActiveCubeFace;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getActiveMipmapLevel = function () {\r\n\r\n\t\t\treturn _currentActiveMipmapLevel;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getRenderTarget = function () {\r\n\r\n\t\t\treturn _currentRenderTarget;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipmapLevel ) {\r\n\r\n\t\t\t_currentRenderTarget = renderTarget;\r\n\t\t\t_currentActiveCubeFace = activeCubeFace;\r\n\t\t\t_currentActiveMipmapLevel = activeMipmapLevel;\r\n\r\n\t\t\tif ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {\r\n\r\n\t\t\t\ttextures.setupRenderTarget( renderTarget );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar framebuffer = _framebuffer;\r\n\t\t\tvar isCube = false;\r\n\r\n\t\t\tif ( renderTarget ) {\r\n\r\n\t\t\t\tvar __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;\r\n\r\n\t\t\t\tif ( renderTarget.isWebGLRenderTargetCube ) {\r\n\r\n\t\t\t\t\tframebuffer = __webglFramebuffer[ activeCubeFace || 0 ];\r\n\t\t\t\t\tisCube = true;\r\n\r\n\t\t\t\t} else if ( renderTarget.isWebGLMultisampleRenderTarget ) {\r\n\r\n\t\t\t\t\tframebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tframebuffer = __webglFramebuffer;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t_currentViewport.copy( renderTarget.viewport );\r\n\t\t\t\t_currentScissor.copy( renderTarget.scissor );\r\n\t\t\t\t_currentScissorTest = renderTarget.scissorTest;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();\r\n\t\t\t\t_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();\r\n\t\t\t\t_currentScissorTest = _scissorTest;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( _currentFramebuffer !== framebuffer ) {\r\n\r\n\t\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\t\t\t\t_currentFramebuffer = framebuffer;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.viewport( _currentViewport );\r\n\t\t\tstate.scissor( _currentScissor );\r\n\t\t\tstate.setScissorTest( _currentScissorTest );\r\n\r\n\t\t\tif ( isCube ) {\r\n\r\n\t\t\t\tvar textureProperties = properties.get( renderTarget.texture );\r\n\t\t\t\t_gl.framebufferTexture2D( 36160, 36064, 34069 + ( activeCubeFace || 0 ), textureProperties.__webglTexture, activeMipmapLevel || 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {\r\n\r\n\t\t\tif ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar framebuffer = properties.get( renderTarget ).__webglFramebuffer;\r\n\r\n\t\t\tif ( renderTarget.isWebGLRenderTargetCube && activeCubeFaceIndex !== undefined ) {\r\n\r\n\t\t\t\tframebuffer = framebuffer[ activeCubeFaceIndex ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( framebuffer ) {\r\n\r\n\t\t\t\tvar restore = false;\r\n\r\n\t\t\t\tif ( framebuffer !== _currentFramebuffer ) {\r\n\r\n\t\t\t\t\t_gl.bindFramebuffer( 36160, framebuffer );\r\n\r\n\t\t\t\t\trestore = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tvar texture = renderTarget.texture;\r\n\t\t\t\t\tvar textureFormat = texture.format;\r\n\t\t\t\t\tvar textureType = texture.type;\r\n\r\n\t\t\t\t\tif ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( 35739 ) ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( 35738 ) && // IE11, Edge and Chrome Mac < 52 (#9513)\r\n\t\t\t\t\t\t! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox\r\n\t\t\t\t\t\t! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( _gl.checkFramebufferStatus( 36160 ) === 36053 ) {\r\n\r\n\t\t\t\t\t\t// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)\r\n\r\n\t\t\t\t\t\tif ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {\r\n\r\n\t\t\t\t\t\t\t_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} finally {\r\n\r\n\t\t\t\t\tif ( restore ) {\r\n\r\n\t\t\t\t\t\t_gl.bindFramebuffer( 36160, _currentFramebuffer );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.copyFramebufferToTexture = function ( position, texture, level ) {\r\n\r\n\t\t\tif ( level === undefined ) { level = 0; }\r\n\r\n\t\t\tvar levelScale = Math.pow( 2, - level );\r\n\t\t\tvar width = Math.floor( texture.image.width * levelScale );\r\n\t\t\tvar height = Math.floor( texture.image.height * levelScale );\r\n\t\t\tvar glFormat = utils.convert( texture.format );\r\n\r\n\t\t\ttextures.setTexture2D( texture, 0 );\r\n\r\n\t\t\t_gl.copyTexImage2D( 3553, level, glFormat, position.x, position.y, width, height, 0 );\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tthis.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {\r\n\r\n\t\t\tvar width = srcTexture.image.width;\r\n\t\t\tvar height = srcTexture.image.height;\r\n\t\t\tvar glFormat = utils.convert( dstTexture.format );\r\n\t\t\tvar glType = utils.convert( dstTexture.type );\r\n\r\n\t\t\ttextures.setTexture2D( dstTexture, 0 );\r\n\r\n\t\t\tif ( srcTexture.isDataTexture ) {\r\n\r\n\t\t\t\t_gl.texSubImage2D( 3553, level || 0, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t_gl.texSubImage2D( 3553, level || 0, position.x, position.y, glFormat, glType, srcTexture.image );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tthis.initTexture = function ( texture ) {\r\n\r\n\t\t\ttextures.setTexture2D( texture, 0 );\r\n\r\n\t\t\tstate.unbindTexture();\r\n\r\n\t\t};\r\n\r\n\t\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction FogExp2( color, density ) {\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.color = new Color( color );\r\n\t\tthis.density = ( density !== undefined ) ? density : 0.00025;\r\n\r\n\t}\r\n\r\n\tObject.assign( FogExp2.prototype, {\r\n\r\n\t\tisFogExp2: true,\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new FogExp2( this.color, this.density );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( /* meta */ ) {\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttype: 'FogExp2',\r\n\t\t\t\tcolor: this.color.getHex(),\r\n\t\t\t\tdensity: this.density\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Fog( color, near, far ) {\r\n\r\n\t\tthis.name = '';\r\n\r\n\t\tthis.color = new Color( color );\r\n\r\n\t\tthis.near = ( near !== undefined ) ? near : 1;\r\n\t\tthis.far = ( far !== undefined ) ? far : 1000;\r\n\r\n\t}\r\n\r\n\tObject.assign( Fog.prototype, {\r\n\r\n\t\tisFog: true,\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Fog( this.color, this.near, this.far );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( /* meta */ ) {\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttype: 'Fog',\r\n\t\t\t\tcolor: this.color.getHex(),\r\n\t\t\t\tnear: this.near,\r\n\t\t\t\tfar: this.far\r\n\t\t\t};\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InterleavedBuffer( array, stride ) {\r\n\r\n\t\tthis.array = array;\r\n\t\tthis.stride = stride;\r\n\t\tthis.count = array !== undefined ? array.length / stride : 0;\r\n\r\n\t\tthis.usage = StaticDrawUsage;\r\n\t\tthis.updateRange = { offset: 0, count: - 1 };\r\n\r\n\t\tthis.version = 0;\r\n\r\n\t}\r\n\r\n\tObject.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', {\r\n\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tif ( value === true ) { this.version ++; }\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBuffer.prototype, {\r\n\r\n\t\tisInterleavedBuffer: true,\r\n\r\n\t\tonUploadCallback: function () {},\r\n\r\n\t\tsetUsage: function ( value ) {\r\n\r\n\t\t\tthis.usage = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.array = new source.array.constructor( source.array );\r\n\t\t\tthis.count = source.count;\r\n\t\t\tthis.stride = source.stride;\r\n\t\t\tthis.usage = source.usage;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopyAt: function ( index1, attribute, index2 ) {\r\n\r\n\t\t\tindex1 *= this.stride;\r\n\t\t\tindex2 *= attribute.stride;\r\n\r\n\t\t\tfor ( var i = 0, l = this.stride; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tset: function ( value, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tthis.array.set( value, offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tonUpload: function ( callback ) {\r\n\r\n\t\t\tthis.onUploadCallback = callback;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) {\r\n\r\n\t\tthis.data = interleavedBuffer;\r\n\t\tthis.itemSize = itemSize;\r\n\t\tthis.offset = offset;\r\n\r\n\t\tthis.normalized = normalized === true;\r\n\r\n\t}\r\n\r\n\tObject.defineProperties( InterleavedBufferAttribute.prototype, {\r\n\r\n\t\tcount: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.data.count;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tarray: {\r\n\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.data.array;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBufferAttribute.prototype, {\r\n\r\n\t\tisInterleavedBufferAttribute: true,\r\n\r\n\t\tsetX: function ( index, x ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset ] = x;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetY: function ( index, y ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetZ: function ( index, z ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetW: function ( index, w ) {\r\n\r\n\t\t\tthis.data.array[ index * this.data.stride + this.offset + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetX: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset ];\r\n\r\n\t\t},\r\n\r\n\t\tgetY: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 1 ];\r\n\r\n\t\t},\r\n\r\n\t\tgetZ: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 2 ];\r\n\r\n\t\t},\r\n\r\n\t\tgetW: function ( index ) {\r\n\r\n\t\t\treturn this.data.array[ index * this.data.stride + this.offset + 3 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetXY: function ( index, x, y ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZ: function ( index, x, y, z ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\t\t\tthis.data.array[ index + 2 ] = z;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetXYZW: function ( index, x, y, z, w ) {\r\n\r\n\t\t\tindex = index * this.data.stride + this.offset;\r\n\r\n\t\t\tthis.data.array[ index + 0 ] = x;\r\n\t\t\tthis.data.array[ index + 1 ] = y;\r\n\t\t\tthis.data.array[ index + 2 ] = z;\r\n\t\t\tthis.data.array[ index + 3 ] = w;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * map: new THREE.Texture( ),\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t * rotation: ,\r\n\t * sizeAttenuation: \r\n\t * }\r\n\t */\r\n\r\n\tfunction SpriteMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'SpriteMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.rotation = 0;\r\n\r\n\t\tthis.sizeAttenuation = true;\r\n\r\n\t\tthis.transparent = true;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tSpriteMaterial.prototype = Object.create( Material.prototype );\r\n\tSpriteMaterial.prototype.constructor = SpriteMaterial;\r\n\tSpriteMaterial.prototype.isSpriteMaterial = true;\r\n\r\n\tSpriteMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.rotation = source.rotation;\r\n\r\n\t\tthis.sizeAttenuation = source.sizeAttenuation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar _geometry;\r\n\r\n\tvar _intersectPoint = new Vector3();\r\n\tvar _worldScale = new Vector3();\r\n\tvar _mvPosition = new Vector3();\r\n\r\n\tvar _alignedPosition = new Vector2();\r\n\tvar _rotatedPosition = new Vector2();\r\n\tvar _viewWorldMatrix = new Matrix4();\r\n\r\n\tvar _vA$1 = new Vector3();\r\n\tvar _vB$1 = new Vector3();\r\n\tvar _vC$1 = new Vector3();\r\n\r\n\tvar _uvA$1 = new Vector2();\r\n\tvar _uvB$1 = new Vector2();\r\n\tvar _uvC$1 = new Vector2();\r\n\r\n\tfunction Sprite( material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Sprite';\r\n\r\n\t\tif ( _geometry === undefined ) {\r\n\r\n\t\t\t_geometry = new BufferGeometry();\r\n\r\n\t\t\tvar float32Array = new Float32Array( [\r\n\t\t\t\t- 0.5, - 0.5, 0, 0, 0,\r\n\t\t\t\t0.5, - 0.5, 0, 1, 0,\r\n\t\t\t\t0.5, 0.5, 0, 1, 1,\r\n\t\t\t\t- 0.5, 0.5, 0, 0, 1\r\n\t\t\t] );\r\n\r\n\t\t\tvar interleavedBuffer = new InterleavedBuffer( float32Array, 5 );\r\n\r\n\t\t\t_geometry.setIndex( [ 0, 1, 2,\t0, 2, 3 ] );\r\n\t\t\t_geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );\r\n\t\t\t_geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );\r\n\r\n\t\t}\r\n\r\n\t\tthis.geometry = _geometry;\r\n\t\tthis.material = ( material !== undefined ) ? material : new SpriteMaterial();\r\n\r\n\t\tthis.center = new Vector2( 0.5, 0.5 );\r\n\r\n\t}\r\n\r\n\tSprite.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Sprite,\r\n\r\n\t\tisSprite: true,\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tif ( raycaster.camera === null ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Sprite: \"Raycaster.camera\" needs to be set in order to raycast against sprites.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t_worldScale.setFromMatrixScale( this.matrixWorld );\r\n\r\n\t\t\t_viewWorldMatrix.copy( raycaster.camera.matrixWorld );\r\n\t\t\tthis.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld );\r\n\r\n\t\t\t_mvPosition.setFromMatrixPosition( this.modelViewMatrix );\r\n\r\n\t\t\tif ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) {\r\n\r\n\t\t\t\t_worldScale.multiplyScalar( - _mvPosition.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar rotation = this.material.rotation;\r\n\t\t\tvar sin, cos;\r\n\t\t\tif ( rotation !== 0 ) {\r\n\r\n\t\t\t\tcos = Math.cos( rotation );\r\n\t\t\t\tsin = Math.sin( rotation );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar center = this.center;\r\n\r\n\t\t\ttransformVertex( _vA$1.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\ttransformVertex( _vB$1.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\ttransformVertex( _vC$1.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\r\n\t\t\t_uvA$1.set( 0, 0 );\r\n\t\t\t_uvB$1.set( 1, 0 );\r\n\t\t\t_uvC$1.set( 1, 1 );\r\n\r\n\t\t\t// check first triangle\r\n\t\t\tvar intersect = raycaster.ray.intersectTriangle( _vA$1, _vB$1, _vC$1, false, _intersectPoint );\r\n\r\n\t\t\tif ( intersect === null ) {\r\n\r\n\t\t\t\t// check second triangle\r\n\t\t\t\ttransformVertex( _vB$1.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );\r\n\t\t\t\t_uvB$1.set( 0, 1 );\r\n\r\n\t\t\t\tintersect = raycaster.ray.intersectTriangle( _vA$1, _vC$1, _vB$1, false, _intersectPoint );\r\n\t\t\t\tif ( intersect === null ) {\r\n\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar distance = raycaster.ray.origin.distanceTo( _intersectPoint );\r\n\r\n\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return; }\r\n\r\n\t\t\tintersects.push( {\r\n\r\n\t\t\t\tdistance: distance,\r\n\t\t\t\tpoint: _intersectPoint.clone(),\r\n\t\t\t\tuv: Triangle.getUV( _intersectPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ),\r\n\t\t\t\tface: null,\r\n\t\t\t\tobject: this\r\n\r\n\t\t\t} );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.material ).copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tif ( source.center !== undefined ) { this.center.copy( source.center ); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\r\n\t} );\r\n\r\n\tfunction transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {\r\n\r\n\t\t// compute position in camera space\r\n\t\t_alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );\r\n\r\n\t\t// to check if rotation is not zero\r\n\t\tif ( sin !== undefined ) {\r\n\r\n\t\t\t_rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );\r\n\t\t\t_rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t_rotatedPosition.copy( _alignedPosition );\r\n\r\n\t\t}\r\n\r\n\r\n\t\tvertexPosition.copy( mvPosition );\r\n\t\tvertexPosition.x += _rotatedPosition.x;\r\n\t\tvertexPosition.y += _rotatedPosition.y;\r\n\r\n\t\t// transform to world space\r\n\t\tvertexPosition.applyMatrix4( _viewWorldMatrix );\r\n\r\n\t}\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _v1$4 = new Vector3();\r\n\tvar _v2$2 = new Vector3();\r\n\r\n\tfunction LOD() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'LOD';\r\n\r\n\t\tObject.defineProperties( this, {\r\n\t\t\tlevels: {\r\n\t\t\t\tenumerable: true,\r\n\t\t\t\tvalue: []\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.autoUpdate = true;\r\n\r\n\t}\r\n\r\n\tLOD.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: LOD,\r\n\r\n\t\tisLOD: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source, false );\r\n\r\n\t\t\tvar levels = source.levels;\r\n\r\n\t\t\tfor ( var i = 0, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar level = levels[ i ];\r\n\r\n\t\t\t\tthis.addLevel( level.object.clone(), level.distance );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.autoUpdate = source.autoUpdate;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\taddLevel: function ( object, distance ) {\r\n\r\n\t\t\tif ( distance === undefined ) { distance = 0; }\r\n\r\n\t\t\tdistance = Math.abs( distance );\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tfor ( var l = 0; l < levels.length; l ++ ) {\r\n\r\n\t\t\t\tif ( distance < levels[ l ].distance ) {\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tlevels.splice( l, 0, { distance: distance, object: object } );\r\n\r\n\t\t\tthis.add( object );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetObjectForDistance: function ( distance ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 0 ) {\r\n\r\n\t\t\t\tfor ( var i = 1, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tif ( distance < levels[ i ].distance ) {\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn levels[ i - 1 ].object;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 0 ) {\r\n\r\n\t\t\t\t_v1$4.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( _v1$4 );\r\n\r\n\t\t\t\tthis.getObjectForDistance( distance ).raycast( raycaster, intersects );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdate: function ( camera ) {\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tif ( levels.length > 1 ) {\r\n\r\n\t\t\t\t_v1$4.setFromMatrixPosition( camera.matrixWorld );\r\n\t\t\t\t_v2$2.setFromMatrixPosition( this.matrixWorld );\r\n\r\n\t\t\t\tvar distance = _v1$4.distanceTo( _v2$2 );\r\n\r\n\t\t\t\tlevels[ 0 ].object.visible = true;\r\n\r\n\t\t\t\tfor ( var i = 1, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tif ( distance >= levels[ i ].distance ) {\r\n\r\n\t\t\t\t\t\tlevels[ i - 1 ].object.visible = false;\r\n\t\t\t\t\t\tlevels[ i ].object.visible = true;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( ; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tlevels[ i ].object.visible = false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tif ( this.autoUpdate === false ) { data.object.autoUpdate = false; }\r\n\r\n\t\t\tdata.object.levels = [];\r\n\r\n\t\t\tvar levels = this.levels;\r\n\r\n\t\t\tfor ( var i = 0, l = levels.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar level = levels[ i ];\r\n\r\n\t\t\t\tdata.object.levels.push( {\r\n\t\t\t\t\tobject: level.object.uuid,\r\n\t\t\t\t\tdistance: level.distance\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tfunction SkinnedMesh( geometry, material ) {\r\n\r\n\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SkinnedMesh no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t}\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'SkinnedMesh';\r\n\r\n\t\tthis.bindMode = 'attached';\r\n\t\tthis.bindMatrix = new Matrix4();\r\n\t\tthis.bindMatrixInverse = new Matrix4();\r\n\r\n\t}\r\n\r\n\tSkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {\r\n\r\n\t\tconstructor: SkinnedMesh,\r\n\r\n\t\tisSkinnedMesh: true,\r\n\r\n\t\tbind: function ( skeleton, bindMatrix ) {\r\n\r\n\t\t\tthis.skeleton = skeleton;\r\n\r\n\t\t\tif ( bindMatrix === undefined ) {\r\n\r\n\t\t\t\tthis.updateMatrixWorld( true );\r\n\r\n\t\t\t\tthis.skeleton.calculateInverses();\r\n\r\n\t\t\t\tbindMatrix = this.matrixWorld;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.bindMatrix.copy( bindMatrix );\r\n\t\t\tthis.bindMatrixInverse.getInverse( bindMatrix );\r\n\r\n\t\t},\r\n\r\n\t\tpose: function () {\r\n\r\n\t\t\tthis.skeleton.pose();\r\n\r\n\t\t},\r\n\r\n\t\tnormalizeSkinWeights: function () {\r\n\r\n\t\t\tvar vector = new Vector4();\r\n\r\n\t\t\tvar skinWeight = this.geometry.attributes.skinWeight;\r\n\r\n\t\t\tfor ( var i = 0, l = skinWeight.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvector.x = skinWeight.getX( i );\r\n\t\t\t\tvector.y = skinWeight.getY( i );\r\n\t\t\t\tvector.z = skinWeight.getZ( i );\r\n\t\t\t\tvector.w = skinWeight.getW( i );\r\n\r\n\t\t\t\tvar scale = 1.0 / vector.manhattanLength();\r\n\r\n\t\t\t\tif ( scale !== Infinity ) {\r\n\r\n\t\t\t\t\tvector.multiplyScalar( scale );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tvector.set( 1, 0, 0, 0 ); // do something reasonable\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tskinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tMesh.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tif ( this.bindMode === 'attached' ) {\r\n\r\n\t\t\t\tthis.bindMatrixInverse.getInverse( this.matrixWorld );\r\n\r\n\t\t\t} else if ( this.bindMode === 'detached' ) {\r\n\r\n\t\t\t\tthis.bindMatrixInverse.getInverse( this.bindMatrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author michael guerrero / http://realitymeltdown.com\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tvar _offsetMatrix = new Matrix4();\r\n\tvar _identityMatrix = new Matrix4();\r\n\r\n\tfunction Skeleton( bones, boneInverses ) {\r\n\r\n\t\t// copy the bone array\r\n\r\n\t\tbones = bones || [];\r\n\r\n\t\tthis.bones = bones.slice( 0 );\r\n\t\tthis.boneMatrices = new Float32Array( this.bones.length * 16 );\r\n\r\n\t\tthis.frame = - 1;\r\n\r\n\t\t// use the supplied bone inverses or calculate the inverses\r\n\r\n\t\tif ( boneInverses === undefined ) {\r\n\r\n\t\t\tthis.calculateInverses();\r\n\r\n\t\t} else {\r\n\r\n\t\t\tif ( this.bones.length === boneInverses.length ) {\r\n\r\n\t\t\t\tthis.boneInverses = boneInverses.slice( 0 );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Skeleton boneInverses is the wrong length.' );\r\n\r\n\t\t\t\tthis.boneInverses = [];\r\n\r\n\t\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tthis.boneInverses.push( new Matrix4() );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Skeleton.prototype, {\r\n\r\n\t\tcalculateInverses: function () {\r\n\r\n\t\t\tthis.boneInverses = [];\r\n\r\n\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar inverse = new Matrix4();\r\n\r\n\t\t\t\tif ( this.bones[ i ] ) {\r\n\r\n\t\t\t\t\tinverse.getInverse( this.bones[ i ].matrixWorld );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.boneInverses.push( inverse );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tpose: function () {\r\n\r\n\t\t\tvar bone, i, il;\r\n\r\n\t\t\t// recover the bind-time world matrices\r\n\r\n\t\t\tfor ( i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tbone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone ) {\r\n\r\n\t\t\t\t\tbone.matrixWorld.getInverse( this.boneInverses[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// compute the local matrices, positions, rotations and scales\r\n\r\n\t\t\tfor ( i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tbone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone ) {\r\n\r\n\t\t\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\t\t\tbone.matrix.getInverse( bone.parent.matrixWorld );\r\n\t\t\t\t\t\tbone.matrix.multiply( bone.matrixWorld );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tbone.matrix.copy( bone.matrixWorld );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbone.matrix.decompose( bone.position, bone.quaternion, bone.scale );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdate: function () {\r\n\r\n\t\t\tvar bones = this.bones;\r\n\t\t\tvar boneInverses = this.boneInverses;\r\n\t\t\tvar boneMatrices = this.boneMatrices;\r\n\t\t\tvar boneTexture = this.boneTexture;\r\n\r\n\t\t\t// flatten bone matrices to array\r\n\r\n\t\t\tfor ( var i = 0, il = bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// compute the offset between the current and the original transform\r\n\r\n\t\t\t\tvar matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix;\r\n\r\n\t\t\t\t_offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] );\r\n\t\t\t\t_offsetMatrix.toArray( boneMatrices, i * 16 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( boneTexture !== undefined ) {\r\n\r\n\t\t\t\tboneTexture.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new Skeleton( this.bones, this.boneInverses );\r\n\r\n\t\t},\r\n\r\n\t\tgetBoneByName: function ( name ) {\r\n\r\n\t\t\tfor ( var i = 0, il = this.bones.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar bone = this.bones[ i ];\r\n\r\n\t\t\t\tif ( bone.name === name ) {\r\n\r\n\t\t\t\t\treturn bone;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn undefined;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mikael emtinger / http://gomo.se/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author ikerr / http://verold.com\r\n\t */\r\n\r\n\tfunction Bone() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Bone';\r\n\r\n\t}\r\n\r\n\tBone.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Bone,\r\n\r\n\t\tisBone: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _instanceLocalMatrix = new Matrix4();\r\n\tvar _instanceWorldMatrix = new Matrix4();\r\n\r\n\tvar _instanceIntersects = [];\r\n\r\n\tvar _mesh = new Mesh();\r\n\r\n\tfunction InstancedMesh( geometry, material, count ) {\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.instanceMatrix = new BufferAttribute( new Float32Array( count * 16 ), 16 );\r\n\r\n\t\tthis.count = count;\r\n\r\n\t}\r\n\r\n\tInstancedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), {\r\n\r\n\t\tconstructor: InstancedMesh,\r\n\r\n\t\tisInstancedMesh: true,\r\n\r\n\t\tgetMatrixAt: function ( index, matrix ) {\r\n\r\n\t\t\tmatrix.fromArray( this.instanceMatrix.array, index * 16 );\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\t\t\tvar raycastTimes = this.count;\r\n\r\n\t\t\t_mesh.geometry = this.geometry;\r\n\t\t\t_mesh.material = this.material;\r\n\r\n\t\t\tif ( _mesh.material === undefined ) { return; }\r\n\r\n\t\t\tfor ( var instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {\r\n\r\n\t\t\t\t// calculate the world matrix for each instance\r\n\r\n\t\t\t\tthis.getMatrixAt( instanceId, _instanceLocalMatrix );\r\n\r\n\t\t\t\t_instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );\r\n\r\n\t\t\t\t// the mesh represents this single instance\r\n\r\n\t\t\t\t_mesh.matrixWorld = _instanceWorldMatrix;\r\n\r\n\t\t\t\t_mesh.raycast( raycaster, _instanceIntersects );\r\n\r\n\t\t\t\t// process the result of raycast\r\n\r\n\t\t\t\tif ( _instanceIntersects.length > 0 ) {\r\n\r\n\t\t\t\t\t_instanceIntersects[ 0 ].instanceId = instanceId;\r\n\t\t\t\t\t_instanceIntersects[ 0 ].object = this;\r\n\r\n\t\t\t\t\tintersects.push( _instanceIntersects[ 0 ] );\r\n\r\n\t\t\t\t\t_instanceIntersects.length = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tsetMatrixAt: function ( index, matrix ) {\r\n\r\n\t\t\tmatrix.toArray( this.instanceMatrix.array, index * 16 );\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * linewidth: ,\r\n\t * linecap: \"round\",\r\n\t * linejoin: \"round\"\r\n\t * }\r\n\t */\r\n\r\n\tfunction LineBasicMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'LineBasicMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.linewidth = 1;\r\n\t\tthis.linecap = 'round';\r\n\t\tthis.linejoin = 'round';\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tLineBasicMaterial.prototype = Object.create( Material.prototype );\r\n\tLineBasicMaterial.prototype.constructor = LineBasicMaterial;\r\n\r\n\tLineBasicMaterial.prototype.isLineBasicMaterial = true;\r\n\r\n\tLineBasicMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.linewidth = source.linewidth;\r\n\t\tthis.linecap = source.linecap;\r\n\t\tthis.linejoin = source.linejoin;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _start = new Vector3();\r\n\tvar _end = new Vector3();\r\n\tvar _inverseMatrix$1 = new Matrix4();\r\n\tvar _ray$1 = new Ray();\r\n\tvar _sphere$2 = new Sphere();\r\n\r\n\tfunction Line( geometry, material, mode ) {\r\n\r\n\t\tif ( mode === 1 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Line: parameter THREE.LinePieces no longer supported. Use THREE.LineSegments instead.' );\r\n\r\n\t\t}\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Line';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t}\r\n\r\n\tLine.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Line,\r\n\r\n\t\tisLine: true,\r\n\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t// we assume non-indexed geometry\r\n\r\n\t\t\t\tif ( geometry.index === null ) {\r\n\r\n\t\t\t\t\tvar positionAttribute = geometry.attributes.position;\r\n\t\t\t\t\tvar lineDistances = [ 0 ];\r\n\r\n\t\t\t\t\tfor ( var i = 1, l = positionAttribute.count; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t_start.fromBufferAttribute( positionAttribute, i - 1 );\r\n\t\t\t\t\t\t_end.fromBufferAttribute( positionAttribute, i );\r\n\r\n\t\t\t\t\t\tlineDistances[ i ] = lineDistances[ i - 1 ];\r\n\t\t\t\t\t\tlineDistances[ i ] += _start.distanceTo( _end );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar lineDistances = geometry.lineDistances;\r\n\r\n\t\t\t\tlineDistances[ 0 ] = 0;\r\n\r\n\t\t\t\tfor ( var i = 1, l = vertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tlineDistances[ i ] = lineDistances[ i - 1 ];\r\n\t\t\t\t\tlineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar precision = raycaster.linePrecision;\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$2.copy( geometry.boundingSphere );\r\n\t\t\t_sphere$2.applyMatrix4( matrixWorld );\r\n\t\t\t_sphere$2.radius += precision;\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere$2 ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix$1.getInverse( matrixWorld );\r\n\t\t\t_ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );\r\n\r\n\t\t\tvar localPrecision = precision / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );\r\n\t\t\tvar localPrecisionSq = localPrecision * localPrecision;\r\n\r\n\t\t\tvar vStart = new Vector3();\r\n\t\t\tvar vEnd = new Vector3();\r\n\t\t\tvar interSegment = new Vector3();\r\n\t\t\tvar interRay = new Vector3();\r\n\t\t\tvar step = ( this && this.isLineSegments ) ? 2 : 1;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar attributes = geometry.attributes;\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = indices.length - 1; i < l; i += step ) {\r\n\r\n\t\t\t\t\t\tvar a = indices[ i ];\r\n\t\t\t\t\t\tvar b = indices[ i + 1 ];\r\n\r\n\t\t\t\t\t\tvStart.fromArray( positions, a * 3 );\r\n\t\t\t\t\t\tvEnd.fromArray( positions, b * 3 );\r\n\r\n\t\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );\r\n\r\n\t\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) {\r\n\r\n\t\t\t\t\t\tvStart.fromArray( positions, 3 * i );\r\n\t\t\t\t\t\tvEnd.fromArray( positions, 3 * i + 3 );\r\n\r\n\t\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );\r\n\r\n\t\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar nbVertices = vertices.length;\r\n\r\n\t\t\t\tfor ( var i = 0; i < nbVertices - 1; i += step ) {\r\n\r\n\t\t\t\t\tvar distSq = _ray$1.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment );\r\n\r\n\t\t\t\t\tif ( distSq > localPrecisionSq ) { continue; }\r\n\r\n\t\t\t\t\tinterRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation\r\n\r\n\t\t\t\t\tvar distance = raycaster.ray.origin.distanceTo( interRay );\r\n\r\n\t\t\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { continue; }\r\n\r\n\t\t\t\t\tintersects.push( {\r\n\r\n\t\t\t\t\t\tdistance: distance,\r\n\t\t\t\t\t\t// What do we want? intersection point on the ray or on the segment??\r\n\t\t\t\t\t\t// point: raycaster.ray.at( distance ),\r\n\t\t\t\t\t\tpoint: interSegment.clone().applyMatrix4( this.matrixWorld ),\r\n\t\t\t\t\t\tindex: i,\r\n\t\t\t\t\t\tface: null,\r\n\t\t\t\t\t\tfaceIndex: null,\r\n\t\t\t\t\t\tobject: this\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _start$1 = new Vector3();\r\n\tvar _end$1 = new Vector3();\r\n\r\n\tfunction LineSegments( geometry, material ) {\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'LineSegments';\r\n\r\n\t}\r\n\r\n\tLineSegments.prototype = Object.assign( Object.create( Line.prototype ), {\r\n\r\n\t\tconstructor: LineSegments,\r\n\r\n\t\tisLineSegments: true,\r\n\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t// we assume non-indexed geometry\r\n\r\n\t\t\t\tif ( geometry.index === null ) {\r\n\r\n\t\t\t\t\tvar positionAttribute = geometry.attributes.position;\r\n\t\t\t\t\tvar lineDistances = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) {\r\n\r\n\t\t\t\t\t\t_start$1.fromBufferAttribute( positionAttribute, i );\r\n\t\t\t\t\t\t_end$1.fromBufferAttribute( positionAttribute, i + 1 );\r\n\r\n\t\t\t\t\t\tlineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];\r\n\t\t\t\t\t\tlineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else if ( geometry.isGeometry ) {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\t\t\t\tvar lineDistances = geometry.lineDistances;\r\n\r\n\t\t\t\tfor ( var i = 0, l = vertices.length; i < l; i += 2 ) {\r\n\r\n\t\t\t\t\t_start$1.copy( vertices[ i ] );\r\n\t\t\t\t\t_end$1.copy( vertices[ i + 1 ] );\r\n\r\n\t\t\t\t\tlineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ];\r\n\t\t\t\t\tlineDistances[ i + 1 ] = lineDistances[ i ] + _start$1.distanceTo( _end$1 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mgreter / http://github.com/mgreter\r\n\t */\r\n\r\n\tfunction LineLoop( geometry, material ) {\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\tthis.type = 'LineLoop';\r\n\r\n\t}\r\n\r\n\tLineLoop.prototype = Object.assign( Object.create( Line.prototype ), {\r\n\r\n\t\tconstructor: LineLoop,\r\n\r\n\t\tisLineLoop: true,\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t * map: new THREE.Texture( ),\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * size: ,\r\n\t * sizeAttenuation: \r\n\t *\r\n\t * morphTargets: \r\n\t * }\r\n\t */\r\n\r\n\tfunction PointsMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'PointsMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.size = 1;\r\n\t\tthis.sizeAttenuation = true;\r\n\r\n\t\tthis.morphTargets = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tPointsMaterial.prototype = Object.create( Material.prototype );\r\n\tPointsMaterial.prototype.constructor = PointsMaterial;\r\n\r\n\tPointsMaterial.prototype.isPointsMaterial = true;\r\n\r\n\tPointsMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.size = source.size;\r\n\t\tthis.sizeAttenuation = source.sizeAttenuation;\r\n\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tvar _inverseMatrix$2 = new Matrix4();\r\n\tvar _ray$2 = new Ray();\r\n\tvar _sphere$3 = new Sphere();\r\n\tvar _position$1 = new Vector3();\r\n\r\n\tfunction Points( geometry, material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Points';\r\n\r\n\t\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\r\n\t\tthis.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } );\r\n\r\n\t\tthis.updateMorphTargets();\r\n\r\n\t}\r\n\r\n\tPoints.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Points,\r\n\r\n\t\tisPoints: true,\r\n\r\n\t\traycast: function ( raycaster, intersects ) {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar matrixWorld = this.matrixWorld;\r\n\t\t\tvar threshold = raycaster.params.Points.threshold;\r\n\r\n\t\t\t// Checking boundingSphere distance to ray\r\n\r\n\t\t\tif ( geometry.boundingSphere === null ) { geometry.computeBoundingSphere(); }\r\n\r\n\t\t\t_sphere$3.copy( geometry.boundingSphere );\r\n\t\t\t_sphere$3.applyMatrix4( matrixWorld );\r\n\t\t\t_sphere$3.radius += threshold;\r\n\r\n\t\t\tif ( raycaster.ray.intersectsSphere( _sphere$3 ) === false ) { return; }\r\n\r\n\t\t\t//\r\n\r\n\t\t\t_inverseMatrix$2.getInverse( matrixWorld );\r\n\t\t\t_ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );\r\n\r\n\t\t\tvar localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );\r\n\t\t\tvar localThresholdSq = localThreshold * localThreshold;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar index = geometry.index;\r\n\t\t\t\tvar attributes = geometry.attributes;\r\n\t\t\t\tvar positions = attributes.position.array;\r\n\r\n\t\t\t\tif ( index !== null ) {\r\n\r\n\t\t\t\t\tvar indices = index.array;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = indices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar a = indices[ i ];\r\n\r\n\t\t\t\t\t\t_position$1.fromArray( positions, a * 3 );\r\n\r\n\t\t\t\t\t\ttestPoint( _position$1, a, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = positions.length / 3; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\t_position$1.fromArray( positions, i * 3 );\r\n\r\n\t\t\t\t\t\ttestPoint( _position$1, i, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar vertices = geometry.vertices;\r\n\r\n\t\t\t\tfor ( var i = 0, l = vertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\ttestPoint( vertices[ i ], i, localThresholdSq, matrixWorld, raycaster, intersects, this );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tupdateMorphTargets: function () {\r\n\r\n\t\t\tvar geometry = this.geometry;\r\n\t\t\tvar m, ml, name;\r\n\r\n\t\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\tvar morphAttributes = geometry.morphAttributes;\r\n\t\t\t\tvar keys = Object.keys( morphAttributes );\r\n\r\n\t\t\t\tif ( keys.length > 0 ) {\r\n\r\n\t\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\r\n\r\n\t\t\t\t\tif ( morphAttribute !== undefined ) {\r\n\r\n\t\t\t\t\t\tthis.morphTargetInfluences = [];\r\n\t\t\t\t\t\tthis.morphTargetDictionary = {};\r\n\r\n\t\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\r\n\r\n\t\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\r\n\r\n\t\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\r\n\t\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar morphTargets = geometry.morphTargets;\r\n\r\n\t\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.Points.updateMorphTargets() does not support THREE.Geometry. Use THREE.BufferGeometry instead.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) {\r\n\r\n\t\tvar rayPointDistanceSq = _ray$2.distanceSqToPoint( point );\r\n\r\n\t\tif ( rayPointDistanceSq < localThresholdSq ) {\r\n\r\n\t\t\tvar intersectPoint = new Vector3();\r\n\r\n\t\t\t_ray$2.closestPointToPoint( point, intersectPoint );\r\n\t\t\tintersectPoint.applyMatrix4( matrixWorld );\r\n\r\n\t\t\tvar distance = raycaster.ray.origin.distanceTo( intersectPoint );\r\n\r\n\t\t\tif ( distance < raycaster.near || distance > raycaster.far ) { return; }\r\n\r\n\t\t\tintersects.push( {\r\n\r\n\t\t\t\tdistance: distance,\r\n\t\t\t\tdistanceToRay: Math.sqrt( rayPointDistanceSq ),\r\n\t\t\t\tpoint: intersectPoint,\r\n\t\t\t\tindex: index,\r\n\t\t\t\tface: null,\r\n\t\t\t\tobject: object\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {\r\n\r\n\t\tTexture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.format = format !== undefined ? format : RGBFormat;\r\n\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : LinearFilter;\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\r\n\t}\r\n\r\n\tVideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), {\r\n\r\n\t\tconstructor: VideoTexture,\r\n\r\n\t\tisVideoTexture: true,\r\n\r\n\t\tupdate: function () {\r\n\r\n\t\t\tvar video = this.image;\r\n\r\n\t\t\tif ( video.readyState >= video.HAVE_CURRENT_DATA ) {\r\n\r\n\t\t\t\tthis.needsUpdate = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\r\n\r\n\t\tthis.image = { width: width, height: height };\r\n\t\tthis.mipmaps = mipmaps;\r\n\r\n\t\t// no flipping for cube textures\r\n\t\t// (also flipping doesn't work for compressed textures )\r\n\r\n\t\tthis.flipY = false;\r\n\r\n\t\t// can't generate mipmaps for compressed textures\r\n\t\t// mips must be embedded in DDS files\r\n\r\n\t\tthis.generateMipmaps = false;\r\n\r\n\t}\r\n\r\n\tCompressedTexture.prototype = Object.create( Texture.prototype );\r\n\tCompressedTexture.prototype.constructor = CompressedTexture;\r\n\r\n\tCompressedTexture.prototype.isCompressedTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {\r\n\r\n\t\tTexture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.needsUpdate = true;\r\n\r\n\t}\r\n\r\n\tCanvasTexture.prototype = Object.create( Texture.prototype );\r\n\tCanvasTexture.prototype.constructor = CanvasTexture;\r\n\tCanvasTexture.prototype.isCanvasTexture = true;\n\n\t/**\r\n\t * @author Matt DesLauriers / @mattdesl\r\n\t * @author atix / arthursilber.de\r\n\t */\r\n\r\n\tfunction DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {\r\n\r\n\t\tformat = format !== undefined ? format : DepthFormat;\r\n\r\n\t\tif ( format !== DepthFormat && format !== DepthStencilFormat ) {\r\n\r\n\t\t\tthrow new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( type === undefined && format === DepthFormat ) { type = UnsignedShortType; }\r\n\t\tif ( type === undefined && format === DepthStencilFormat ) { type = UnsignedInt248Type; }\r\n\r\n\t\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );\r\n\r\n\t\tthis.image = { width: width, height: height };\r\n\r\n\t\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\r\n\t\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\r\n\r\n\t\tthis.flipY = false;\r\n\t\tthis.generateMipmaps\t= false;\r\n\r\n\t}\r\n\r\n\tDepthTexture.prototype = Object.create( Texture.prototype );\r\n\tDepthTexture.prototype.constructor = DepthTexture;\r\n\tDepthTexture.prototype.isDepthTexture = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction WireframeGeometry( geometry ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'WireframeGeometry';\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, j, l, o, ol;\r\n\t\tvar edge = [ 0, 0 ], edges = {}, e, edge1, edge2;\r\n\t\tvar key, keys = [ 'a', 'b', 'c' ];\r\n\t\tvar vertex;\r\n\r\n\t\t// different logic for Geometry and BufferGeometry\r\n\r\n\t\tif ( geometry && geometry.isGeometry ) {\r\n\r\n\t\t\t// create a data structure that contains all edges without duplicates\r\n\r\n\t\t\tvar faces = geometry.faces;\r\n\r\n\t\t\tfor ( i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\tedge1 = face[ keys[ j ] ];\r\n\t\t\t\t\tedge2 = face[ keys[ ( j + 1 ) % 3 ] ];\r\n\t\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates\r\n\t\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate vertices\r\n\r\n\t\t\tfor ( key in edges ) {\r\n\r\n\t\t\t\te = edges[ key ];\r\n\r\n\t\t\t\tvertex = geometry.vertices[ e.index1 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\tvertex = geometry.vertices[ e.index2 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( geometry && geometry.isBufferGeometry ) {\r\n\r\n\t\t\tvar position, indices, groups;\r\n\t\t\tvar group, start, count;\r\n\t\t\tvar index1, index2;\r\n\r\n\t\t\tvertex = new Vector3();\r\n\r\n\t\t\tif ( geometry.index !== null ) {\r\n\r\n\t\t\t\t// indexed BufferGeometry\r\n\r\n\t\t\t\tposition = geometry.attributes.position;\r\n\t\t\t\tindices = geometry.index;\r\n\t\t\t\tgroups = geometry.groups;\r\n\r\n\t\t\t\tif ( groups.length === 0 ) {\r\n\r\n\t\t\t\t\tgroups = [ { start: 0, count: indices.count, materialIndex: 0 } ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// create a data structure that contains all eges without duplicates\r\n\r\n\t\t\t\tfor ( o = 0, ol = groups.length; o < ol; ++ o ) {\r\n\r\n\t\t\t\t\tgroup = groups[ o ];\r\n\r\n\t\t\t\t\tstart = group.start;\r\n\t\t\t\t\tcount = group.count;\r\n\r\n\t\t\t\t\tfor ( i = start, l = ( start + count ); i < l; i += 3 ) {\r\n\r\n\t\t\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tedge1 = indices.getX( i + j );\r\n\t\t\t\t\t\t\tedge2 = indices.getX( i + ( j + 1 ) % 3 );\r\n\t\t\t\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates\r\n\t\t\t\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] };\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// generate vertices\r\n\r\n\t\t\t\tfor ( key in edges ) {\r\n\r\n\t\t\t\t\te = edges[ key ];\r\n\r\n\t\t\t\t\tvertex.fromBufferAttribute( position, e.index1 );\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\tvertex.fromBufferAttribute( position, e.index2 );\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// non-indexed BufferGeometry\r\n\r\n\t\t\t\tposition = geometry.attributes.position;\r\n\r\n\t\t\t\tfor ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) {\r\n\r\n\t\t\t\t\tfor ( j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\t\t\t// three edges per triangle, an edge is represented as (index1, index2)\r\n\t\t\t\t\t\t// e.g. the first triangle has the following edges: (0,1),(1,2),(2,0)\r\n\r\n\t\t\t\t\t\tindex1 = 3 * i + j;\r\n\t\t\t\t\t\tvertex.fromBufferAttribute( position, index1 );\r\n\t\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t\tindex2 = 3 * i + ( ( j + 1 ) % 3 );\r\n\t\t\t\t\t\tvertex.fromBufferAttribute( position, index2 );\r\n\t\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\r\n\t}\r\n\r\n\tWireframeGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tWireframeGeometry.prototype.constructor = WireframeGeometry;\n\n\t/**\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * Parametric Surfaces Geometry\r\n\t * based on the brilliant article by @prideout http://prideout.net/blog/?p=44\r\n\t */\r\n\r\n\t// ParametricGeometry\r\n\r\n\tfunction ParametricGeometry( func, slices, stacks ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ParametricGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tfunc: func,\r\n\t\t\tslices: slices,\r\n\t\t\tstacks: stacks\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tParametricGeometry.prototype = Object.create( Geometry.prototype );\r\n\tParametricGeometry.prototype.constructor = ParametricGeometry;\r\n\r\n\t// ParametricBufferGeometry\r\n\r\n\tfunction ParametricBufferGeometry( func, slices, stacks ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ParametricBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tfunc: func,\r\n\t\t\tslices: slices,\r\n\t\t\tstacks: stacks\r\n\t\t};\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\tvar EPS = 0.00001;\r\n\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar p0 = new Vector3(), p1 = new Vector3();\r\n\t\tvar pu = new Vector3(), pv = new Vector3();\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tif ( func.length < 3 ) {\r\n\r\n\t\t\tconsole.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );\r\n\r\n\t\t}\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tvar sliceCount = slices + 1;\r\n\r\n\t\tfor ( i = 0; i <= stacks; i ++ ) {\r\n\r\n\t\t\tvar v = i / stacks;\r\n\r\n\t\t\tfor ( j = 0; j <= slices; j ++ ) {\r\n\r\n\t\t\t\tvar u = j / slices;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tfunc( u, v, p0 );\r\n\t\t\t\tvertices.push( p0.x, p0.y, p0.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\t// approximate tangent vectors via finite differences\r\n\r\n\t\t\t\tif ( u - EPS >= 0 ) {\r\n\r\n\t\t\t\t\tfunc( u - EPS, v, p1 );\r\n\t\t\t\t\tpu.subVectors( p0, p1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfunc( u + EPS, v, p1 );\r\n\t\t\t\t\tpu.subVectors( p1, p0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( v - EPS >= 0 ) {\r\n\r\n\t\t\t\t\tfunc( u, v - EPS, p1 );\r\n\t\t\t\t\tpv.subVectors( p0, p1 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tfunc( u, v + EPS, p1 );\r\n\t\t\t\t\tpv.subVectors( p1, p0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// cross product of tangent vectors returns surface normal\r\n\r\n\t\t\t\tnormal.crossVectors( pu, pv ).normalize();\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( u, v );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( i = 0; i < stacks; i ++ ) {\r\n\r\n\t\t\tfor ( j = 0; j < slices; j ++ ) {\r\n\r\n\t\t\t\tvar a = i * sliceCount + j;\r\n\t\t\t\tvar b = i * sliceCount + j + 1;\r\n\t\t\t\tvar c = ( i + 1 ) * sliceCount + j + 1;\r\n\t\t\t\tvar d = ( i + 1 ) * sliceCount + j;\r\n\r\n\t\t\t\t// faces one and two\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;\n\n\t/**\r\n\t * @author clockworkgeek / https://github.com/clockworkgeek\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// PolyhedronGeometry\r\n\r\n\tfunction PolyhedronGeometry( vertices, indices, radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'PolyhedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tvertices: vertices,\r\n\t\t\tindices: indices,\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tPolyhedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tPolyhedronGeometry.prototype.constructor = PolyhedronGeometry;\r\n\r\n\t// PolyhedronBufferGeometry\r\n\r\n\tfunction PolyhedronBufferGeometry( vertices, indices, radius, detail ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'PolyhedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tvertices: vertices,\r\n\t\t\tindices: indices,\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\tdetail = detail || 0;\r\n\r\n\t\t// default buffer data\r\n\r\n\t\tvar vertexBuffer = [];\r\n\t\tvar uvBuffer = [];\r\n\r\n\t\t// the subdivision creates the vertex buffer data\r\n\r\n\t\tsubdivide( detail );\r\n\r\n\t\t// all vertices should lie on a conceptual sphere with a given radius\r\n\r\n\t\tapplyRadius( radius );\r\n\r\n\t\t// finally, create the uv data\r\n\r\n\t\tgenerateUVs();\r\n\r\n\t\t// build non-indexed geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );\r\n\r\n\t\tif ( detail === 0 ) {\r\n\r\n\t\t\tthis.computeVertexNormals(); // flat normals\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.normalizeNormals(); // smooth normals\r\n\r\n\t\t}\r\n\r\n\t\t// helper functions\r\n\r\n\t\tfunction subdivide( detail ) {\r\n\r\n\t\t\tvar a = new Vector3();\r\n\t\t\tvar b = new Vector3();\r\n\t\t\tvar c = new Vector3();\r\n\r\n\t\t\t// iterate over all faces and apply a subdivison with the given detail value\r\n\r\n\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\r\n\r\n\t\t\t\t// get the vertices of the face\r\n\r\n\t\t\t\tgetVertexByIndex( indices[ i + 0 ], a );\r\n\t\t\t\tgetVertexByIndex( indices[ i + 1 ], b );\r\n\t\t\t\tgetVertexByIndex( indices[ i + 2 ], c );\r\n\r\n\t\t\t\t// perform subdivision\r\n\r\n\t\t\t\tsubdivideFace( a, b, c, detail );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction subdivideFace( a, b, c, detail ) {\r\n\r\n\t\t\tvar cols = Math.pow( 2, detail );\r\n\r\n\t\t\t// we use this multidimensional array as a data structure for creating the subdivision\r\n\r\n\t\t\tvar v = [];\r\n\r\n\t\t\tvar i, j;\r\n\r\n\t\t\t// construct all of the vertices for this subdivision\r\n\r\n\t\t\tfor ( i = 0; i <= cols; i ++ ) {\r\n\r\n\t\t\t\tv[ i ] = [];\r\n\r\n\t\t\t\tvar aj = a.clone().lerp( c, i / cols );\r\n\t\t\t\tvar bj = b.clone().lerp( c, i / cols );\r\n\r\n\t\t\t\tvar rows = cols - i;\r\n\r\n\t\t\t\tfor ( j = 0; j <= rows; j ++ ) {\r\n\r\n\t\t\t\t\tif ( j === 0 && i === cols ) {\r\n\r\n\t\t\t\t\t\tv[ i ][ j ] = aj;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tv[ i ][ j ] = aj.clone().lerp( bj, j / rows );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// construct all of the faces\r\n\r\n\t\t\tfor ( i = 0; i < cols; i ++ ) {\r\n\r\n\t\t\t\tfor ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {\r\n\r\n\t\t\t\t\tvar k = Math.floor( j / 2 );\r\n\r\n\t\t\t\t\tif ( j % 2 === 0 ) {\r\n\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k ] );\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tpushVertex( v[ i ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k + 1 ] );\r\n\t\t\t\t\t\tpushVertex( v[ i + 1 ][ k ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction applyRadius( radius ) {\r\n\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\t// iterate over the entire buffer and apply the radius to each vertex\r\n\r\n\t\t\tfor ( var i = 0; i < vertexBuffer.length; i += 3 ) {\r\n\r\n\t\t\t\tvertex.x = vertexBuffer[ i + 0 ];\r\n\t\t\t\tvertex.y = vertexBuffer[ i + 1 ];\r\n\t\t\t\tvertex.z = vertexBuffer[ i + 2 ];\r\n\r\n\t\t\t\tvertex.normalize().multiplyScalar( radius );\r\n\r\n\t\t\t\tvertexBuffer[ i + 0 ] = vertex.x;\r\n\t\t\t\tvertexBuffer[ i + 1 ] = vertex.y;\r\n\t\t\t\tvertexBuffer[ i + 2 ] = vertex.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateUVs() {\r\n\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tfor ( var i = 0; i < vertexBuffer.length; i += 3 ) {\r\n\r\n\t\t\t\tvertex.x = vertexBuffer[ i + 0 ];\r\n\t\t\t\tvertex.y = vertexBuffer[ i + 1 ];\r\n\t\t\t\tvertex.z = vertexBuffer[ i + 2 ];\r\n\r\n\t\t\t\tvar u = azimuth( vertex ) / 2 / Math.PI + 0.5;\r\n\t\t\t\tvar v = inclination( vertex ) / Math.PI + 0.5;\r\n\t\t\t\tuvBuffer.push( u, 1 - v );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcorrectUVs();\r\n\r\n\t\t\tcorrectSeam();\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctSeam() {\r\n\r\n\t\t\t// handle case when face straddles the seam, see #3269\r\n\r\n\t\t\tfor ( var i = 0; i < uvBuffer.length; i += 6 ) {\r\n\r\n\t\t\t\t// uv data of a single face\r\n\r\n\t\t\t\tvar x0 = uvBuffer[ i + 0 ];\r\n\t\t\t\tvar x1 = uvBuffer[ i + 2 ];\r\n\t\t\t\tvar x2 = uvBuffer[ i + 4 ];\r\n\r\n\t\t\t\tvar max = Math.max( x0, x1, x2 );\r\n\t\t\t\tvar min = Math.min( x0, x1, x2 );\r\n\r\n\t\t\t\t// 0.9 is somewhat arbitrary\r\n\r\n\t\t\t\tif ( max > 0.9 && min < 0.1 ) {\r\n\r\n\t\t\t\t\tif ( x0 < 0.2 ) { uvBuffer[ i + 0 ] += 1; }\r\n\t\t\t\t\tif ( x1 < 0.2 ) { uvBuffer[ i + 2 ] += 1; }\r\n\t\t\t\t\tif ( x2 < 0.2 ) { uvBuffer[ i + 4 ] += 1; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction pushVertex( vertex ) {\r\n\r\n\t\t\tvertexBuffer.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t}\r\n\r\n\t\tfunction getVertexByIndex( index, vertex ) {\r\n\r\n\t\t\tvar stride = index * 3;\r\n\r\n\t\t\tvertex.x = vertices[ stride + 0 ];\r\n\t\t\tvertex.y = vertices[ stride + 1 ];\r\n\t\t\tvertex.z = vertices[ stride + 2 ];\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctUVs() {\r\n\r\n\t\t\tvar a = new Vector3();\r\n\t\t\tvar b = new Vector3();\r\n\t\t\tvar c = new Vector3();\r\n\r\n\t\t\tvar centroid = new Vector3();\r\n\r\n\t\t\tvar uvA = new Vector2();\r\n\t\t\tvar uvB = new Vector2();\r\n\t\t\tvar uvC = new Vector2();\r\n\r\n\t\t\tfor ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {\r\n\r\n\t\t\t\ta.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );\r\n\t\t\t\tb.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );\r\n\t\t\t\tc.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );\r\n\r\n\t\t\t\tuvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );\r\n\t\t\t\tuvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );\r\n\t\t\t\tuvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );\r\n\r\n\t\t\t\tcentroid.copy( a ).add( b ).add( c ).divideScalar( 3 );\r\n\r\n\t\t\t\tvar azi = azimuth( centroid );\r\n\r\n\t\t\t\tcorrectUV( uvA, j + 0, a, azi );\r\n\t\t\t\tcorrectUV( uvB, j + 2, b, azi );\r\n\t\t\t\tcorrectUV( uvC, j + 4, c, azi );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction correctUV( uv, stride, vector, azimuth ) {\r\n\r\n\t\t\tif ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {\r\n\r\n\t\t\t\tuvBuffer[ stride ] = uv.x - 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {\r\n\r\n\t\t\t\tuvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Angle around the Y axis, counter-clockwise when looking from above.\r\n\r\n\t\tfunction azimuth( vector ) {\r\n\r\n\t\t\treturn Math.atan2( vector.z, - vector.x );\r\n\r\n\t\t}\r\n\r\n\r\n\t\t// Angle above the XZ plane.\r\n\r\n\t\tfunction inclination( vector ) {\r\n\r\n\t\t\treturn Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tPolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tPolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// TetrahedronGeometry\r\n\r\n\tfunction TetrahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TetrahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTetrahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTetrahedronGeometry.prototype.constructor = TetrahedronGeometry;\r\n\r\n\t// TetrahedronBufferGeometry\r\n\r\n\tfunction TetrahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar vertices = [\r\n\t\t\t1, 1, 1, \t- 1, - 1, 1, \t- 1, 1, - 1, \t1, - 1, - 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t2, 1, 0, \t0, 3, 2,\t1, 3, 0,\t2, 3, 1\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'TetrahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tTetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tTetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// OctahedronGeometry\r\n\r\n\tfunction OctahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'OctahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tOctahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tOctahedronGeometry.prototype.constructor = OctahedronGeometry;\r\n\r\n\t// OctahedronBufferGeometry\r\n\r\n\tfunction OctahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar vertices = [\r\n\t\t\t1, 0, 0, \t- 1, 0, 0,\t0, 1, 0,\r\n\t\t\t0, - 1, 0, \t0, 0, 1,\t0, 0, - 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t0, 2, 4,\t0, 4, 3,\t0, 3, 5,\r\n\t\t\t0, 5, 2,\t1, 2, 5,\t1, 5, 3,\r\n\t\t\t1, 3, 4,\t1, 4, 2\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'OctahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tOctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tOctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry;\n\n\t/**\r\n\t * @author timothypratley / https://github.com/timothypratley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// IcosahedronGeometry\r\n\r\n\tfunction IcosahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'IcosahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tIcosahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tIcosahedronGeometry.prototype.constructor = IcosahedronGeometry;\r\n\r\n\t// IcosahedronBufferGeometry\r\n\r\n\tfunction IcosahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar t = ( 1 + Math.sqrt( 5 ) ) / 2;\r\n\r\n\t\tvar vertices = [\r\n\t\t\t- 1, t, 0, \t1, t, 0, \t- 1, - t, 0, \t1, - t, 0,\r\n\t\t\t 0, - 1, t, \t0, 1, t,\t0, - 1, - t, \t0, 1, - t,\r\n\t\t\t t, 0, - 1, \tt, 0, 1, \t- t, 0, - 1, \t- t, 0, 1\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t 0, 11, 5, \t0, 5, 1, \t0, 1, 7, \t0, 7, 10, \t0, 10, 11,\r\n\t\t\t 1, 5, 9, \t5, 11, 4,\t11, 10, 2,\t10, 7, 6,\t7, 1, 8,\r\n\t\t\t 3, 9, 4, \t3, 4, 2,\t3, 2, 6,\t3, 6, 8,\t3, 8, 9,\r\n\t\t\t 4, 9, 5, \t2, 4, 11,\t6, 2, 10,\t8, 6, 7,\t9, 8, 1\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'IcosahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tIcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tIcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry;\n\n\t/**\r\n\t * @author Abe Pazos / https://hamoid.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// DodecahedronGeometry\r\n\r\n\tfunction DodecahedronGeometry( radius, detail ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'DodecahedronGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tDodecahedronGeometry.prototype = Object.create( Geometry.prototype );\r\n\tDodecahedronGeometry.prototype.constructor = DodecahedronGeometry;\r\n\r\n\t// DodecahedronBufferGeometry\r\n\r\n\tfunction DodecahedronBufferGeometry( radius, detail ) {\r\n\r\n\t\tvar t = ( 1 + Math.sqrt( 5 ) ) / 2;\r\n\t\tvar r = 1 / t;\r\n\r\n\t\tvar vertices = [\r\n\r\n\t\t\t// (±1, ±1, ±1)\r\n\t\t\t- 1, - 1, - 1,\t- 1, - 1, 1,\r\n\t\t\t- 1, 1, - 1, - 1, 1, 1,\r\n\t\t\t1, - 1, - 1, 1, - 1, 1,\r\n\t\t\t1, 1, - 1, 1, 1, 1,\r\n\r\n\t\t\t// (0, ±1/φ, ±φ)\r\n\t\t\t 0, - r, - t, 0, - r, t,\r\n\t\t\t 0, r, - t, 0, r, t,\r\n\r\n\t\t\t// (±1/φ, ±φ, 0)\r\n\t\t\t- r, - t, 0, - r, t, 0,\r\n\t\t\t r, - t, 0, r, t, 0,\r\n\r\n\t\t\t// (±φ, 0, ±1/φ)\r\n\t\t\t- t, 0, - r, t, 0, - r,\r\n\t\t\t- t, 0, r, t, 0, r\r\n\t\t];\r\n\r\n\t\tvar indices = [\r\n\t\t\t3, 11, 7, \t3, 7, 15, \t3, 15, 13,\r\n\t\t\t7, 19, 17, \t7, 17, 6, \t7, 6, 15,\r\n\t\t\t17, 4, 8, \t17, 8, 10, \t17, 10, 6,\r\n\t\t\t8, 0, 16, \t8, 16, 2, \t8, 2, 10,\r\n\t\t\t0, 12, 1, \t0, 1, 18, \t0, 18, 16,\r\n\t\t\t6, 10, 2, \t6, 2, 13, \t6, 13, 15,\r\n\t\t\t2, 16, 18, \t2, 18, 3, \t2, 3, 13,\r\n\t\t\t18, 1, 9, \t18, 9, 11, \t18, 11, 3,\r\n\t\t\t4, 14, 12, \t4, 12, 0, \t4, 0, 8,\r\n\t\t\t11, 9, 5, \t11, 5, 19, \t11, 19, 7,\r\n\t\t\t19, 5, 14, \t19, 14, 4, \t19, 4, 17,\r\n\t\t\t1, 12, 14, \t1, 14, 5, \t1, 5, 9\r\n\t\t];\r\n\r\n\t\tPolyhedronBufferGeometry.call( this, vertices, indices, radius, detail );\r\n\r\n\t\tthis.type = 'DodecahedronBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tdetail: detail\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tDodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype );\r\n\tDodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry;\n\n\t/**\r\n\t * @author oosmoxiecode / https://github.com/oosmoxiecode\r\n\t * @author WestLangley / https://github.com/WestLangley\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author miningold / https://github.com/miningold\r\n\t * @author jonobr1 / https://github.com/jonobr1\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t */\r\n\r\n\t// TubeGeometry\r\n\r\n\tfunction TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TubeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpath: path,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradius: radius,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tclosed: closed\r\n\t\t};\r\n\r\n\t\tif ( taper !== undefined ) { console.warn( 'THREE.TubeGeometry: taper has been removed.' ); }\r\n\r\n\t\tvar bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed );\r\n\r\n\t\t// expose internals\r\n\r\n\t\tthis.tangents = bufferGeometry.tangents;\r\n\t\tthis.normals = bufferGeometry.normals;\r\n\t\tthis.binormals = bufferGeometry.binormals;\r\n\r\n\t\t// create geometry\r\n\r\n\t\tthis.fromBufferGeometry( bufferGeometry );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTubeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTubeGeometry.prototype.constructor = TubeGeometry;\r\n\r\n\t// TubeBufferGeometry\r\n\r\n\tfunction TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TubeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpath: path,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradius: radius,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tclosed: closed\r\n\t\t};\r\n\r\n\t\ttubularSegments = tubularSegments || 64;\r\n\t\tradius = radius || 1;\r\n\t\tradialSegments = radialSegments || 8;\r\n\t\tclosed = closed || false;\r\n\r\n\t\tvar frames = path.computeFrenetFrames( tubularSegments, closed );\r\n\r\n\t\t// expose internals\r\n\r\n\t\tthis.tangents = frames.tangents;\r\n\t\tthis.normals = frames.normals;\r\n\t\tthis.binormals = frames.binormals;\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar P = new Vector3();\r\n\r\n\t\tvar i, j;\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\t\tvar indices = [];\r\n\r\n\t\t// create buffer data\r\n\r\n\t\tgenerateBufferData();\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// functions\r\n\r\n\t\tfunction generateBufferData() {\r\n\r\n\t\t\tfor ( i = 0; i < tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tgenerateSegment( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// if the geometry is not closed, generate the last row of vertices and normals\r\n\t\t\t// at the regular position on the given path\r\n\t\t\t//\r\n\t\t\t// if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ)\r\n\r\n\t\t\tgenerateSegment( ( closed === false ) ? tubularSegments : 0 );\r\n\r\n\t\t\t// uvs are generated in a separate function.\r\n\t\t\t// this makes it easy compute correct values for closed geometries\r\n\r\n\t\t\tgenerateUVs();\r\n\r\n\t\t\t// finally create faces\r\n\r\n\t\t\tgenerateIndices();\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateSegment( i ) {\r\n\r\n\t\t\t// we use getPointAt to sample evenly distributed points from the given path\r\n\r\n\t\t\tP = path.getPointAt( i / tubularSegments, P );\r\n\r\n\t\t\t// retrieve corresponding normal and binormal\r\n\r\n\t\t\tvar N = frames.normals[ i ];\r\n\t\t\tvar B = frames.binormals[ i ];\r\n\r\n\t\t\t// generate normals and vertices for the current segment\r\n\r\n\t\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\r\n\t\t\t\tvar sin = Math.sin( v );\r\n\t\t\t\tvar cos = - Math.cos( v );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormal.x = ( cos * N.x + sin * B.x );\r\n\t\t\t\tnormal.y = ( cos * N.y + sin * B.y );\r\n\t\t\t\tnormal.z = ( cos * N.z + sin * B.z );\r\n\t\t\t\tnormal.normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = P.x + radius * normal.x;\r\n\t\t\t\tvertex.y = P.y + radius * normal.y;\r\n\t\t\t\tvertex.z = P.z + radius * normal.z;\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateIndices() {\r\n\r\n\t\t\tfor ( j = 1; j <= tubularSegments; j ++ ) {\r\n\r\n\t\t\t\tfor ( i = 1; i <= radialSegments; i ++ ) {\r\n\r\n\t\t\t\t\tvar a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );\r\n\t\t\t\t\tvar b = ( radialSegments + 1 ) * j + ( i - 1 );\r\n\t\t\t\t\tvar c = ( radialSegments + 1 ) * j + i;\r\n\t\t\t\t\tvar d = ( radialSegments + 1 ) * ( j - 1 ) + i;\r\n\r\n\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateUVs() {\r\n\r\n\t\t\tfor ( i = 0; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\t\t\tuv.x = i / tubularSegments;\r\n\t\t\t\t\tuv.y = j / radialSegments;\r\n\r\n\t\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tTubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTubeBufferGeometry.prototype.constructor = TubeBufferGeometry;\r\n\r\n\tTubeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tdata.path = this.parameters.path.toJSON();\r\n\r\n\t\treturn data;\r\n\r\n\t};\n\n\t/**\r\n\t * @author oosmoxiecode\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * based on http://www.blackpawn.com/texts/pqtorus/\r\n\t */\r\n\r\n\t// TorusKnotGeometry\r\n\r\n\tfunction TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusKnotGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tp: p,\r\n\t\t\tq: q\r\n\t\t};\r\n\r\n\t\tif ( heightScale !== undefined ) { console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); }\r\n\r\n\t\tthis.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTorusKnotGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTorusKnotGeometry.prototype.constructor = TorusKnotGeometry;\r\n\r\n\t// TorusKnotBufferGeometry\r\n\r\n\tfunction TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusKnotBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\tp: p,\r\n\t\t\tq: q\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\ttube = tube || 0.4;\r\n\t\ttubularSegments = Math.floor( tubularSegments ) || 64;\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\tp = p || 2;\r\n\t\tq = q || 3;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, j;\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar P1 = new Vector3();\r\n\t\tvar P2 = new Vector3();\r\n\r\n\t\tvar B = new Vector3();\r\n\t\tvar T = new Vector3();\r\n\t\tvar N = new Vector3();\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( i = 0; i <= tubularSegments; ++ i ) {\r\n\r\n\t\t\t// the radian \"u\" is used to calculate the position on the torus curve of the current tubular segement\r\n\r\n\t\t\tvar u = i / tubularSegments * p * Math.PI * 2;\r\n\r\n\t\t\t// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.\r\n\t\t\t// these points are used to create a special \"coordinate space\", which is necessary to calculate the correct vertex positions\r\n\r\n\t\t\tcalculatePositionOnCurve( u, p, q, radius, P1 );\r\n\t\t\tcalculatePositionOnCurve( u + 0.01, p, q, radius, P2 );\r\n\r\n\t\t\t// calculate orthonormal basis\r\n\r\n\t\t\tT.subVectors( P2, P1 );\r\n\t\t\tN.addVectors( P2, P1 );\r\n\t\t\tB.crossVectors( T, N );\r\n\t\t\tN.crossVectors( B, T );\r\n\r\n\t\t\t// normalize B, N. T can be ignored, we don't use it\r\n\r\n\t\t\tB.normalize();\r\n\t\t\tN.normalize();\r\n\r\n\t\t\tfor ( j = 0; j <= radialSegments; ++ j ) {\r\n\r\n\t\t\t\t// now calculate the vertices. they are nothing more than an extrusion of the torus curve.\r\n\t\t\t\t// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.\r\n\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\t\t\t\tvar cx = - tube * Math.cos( v );\r\n\t\t\t\tvar cy = tube * Math.sin( v );\r\n\r\n\t\t\t\t// now calculate the final vertex position.\r\n\t\t\t\t// first we orient the extrusion with our basis vectos, then we add it to the current position on the curve\r\n\r\n\t\t\t\tvertex.x = P1.x + ( cx * N.x + cy * B.x );\r\n\t\t\t\tvertex.y = P1.y + ( cx * N.y + cy * B.y );\r\n\t\t\t\tvertex.z = P1.z + ( cx * N.z + cy * B.z );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)\r\n\r\n\t\t\t\tnormal.subVectors( vertex, P1 ).normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( i / tubularSegments );\r\n\t\t\t\tuvs.push( j / radialSegments );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( j = 1; j <= tubularSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 1; i <= radialSegments; i ++ ) {\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\tvar a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );\r\n\t\t\t\tvar b = ( radialSegments + 1 ) * j + ( i - 1 );\r\n\t\t\t\tvar c = ( radialSegments + 1 ) * j + i;\r\n\t\t\t\tvar d = ( radialSegments + 1 ) * ( j - 1 ) + i;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// this function calculates the current position on the torus curve\r\n\r\n\t\tfunction calculatePositionOnCurve( u, p, q, radius, position ) {\r\n\r\n\t\t\tvar cu = Math.cos( u );\r\n\t\t\tvar su = Math.sin( u );\r\n\t\t\tvar quOverP = q / p * u;\r\n\t\t\tvar cs = Math.cos( quOverP );\r\n\r\n\t\t\tposition.x = radius * ( 2 + cs ) * 0.5 * cu;\r\n\t\t\tposition.y = radius * ( 2 + cs ) * su * 0.5;\r\n\t\t\tposition.z = radius * Math.sin( quOverP ) * 0.5;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tTorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry;\n\n\t/**\r\n\t * @author oosmoxiecode\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// TorusGeometry\r\n\r\n\tfunction TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tarc: arc\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTorusGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTorusGeometry.prototype.constructor = TorusGeometry;\r\n\r\n\t// TorusBufferGeometry\r\n\r\n\tfunction TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'TorusBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\ttube: tube,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\ttubularSegments: tubularSegments,\r\n\t\t\tarc: arc\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\ttube = tube || 0.4;\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\ttubularSegments = Math.floor( tubularSegments ) || 6;\r\n\t\tarc = arc || Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar center = new Vector3();\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\tvar j, i;\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( j = 0; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 0; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\tvar u = i / tubularSegments * arc;\r\n\t\t\t\tvar v = j / radialSegments * Math.PI * 2;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );\r\n\t\t\t\tvertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );\r\n\t\t\t\tvertex.z = tube * Math.sin( v );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tcenter.x = radius * Math.cos( u );\r\n\t\t\t\tcenter.y = radius * Math.sin( u );\r\n\t\t\t\tnormal.subVectors( vertex, center ).normalize();\r\n\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( i / tubularSegments );\r\n\t\t\t\tuvs.push( j / radialSegments );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate indices\r\n\r\n\t\tfor ( j = 1; j <= radialSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 1; i <= tubularSegments; i ++ ) {\r\n\r\n\t\t\t\t// indices\r\n\r\n\t\t\t\tvar a = ( tubularSegments + 1 ) * j + i - 1;\r\n\t\t\t\tvar b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;\r\n\t\t\t\tvar c = ( tubularSegments + 1 ) * ( j - 1 ) + i;\r\n\t\t\t\tvar d = ( tubularSegments + 1 ) * j + i;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tTorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tTorusBufferGeometry.prototype.constructor = TorusBufferGeometry;\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * Port from https://github.com/mapbox/earcut (v2.1.5)\r\n\t */\r\n\r\n\tvar Earcut = {\r\n\r\n\t\ttriangulate: function ( data, holeIndices, dim ) {\r\n\r\n\t\t\tdim = dim || 2;\r\n\r\n\t\t\tvar hasHoles = holeIndices && holeIndices.length,\r\n\t\t\t\touterLen = hasHoles ? holeIndices[ 0 ] * dim : data.length,\r\n\t\t\t\touterNode = linkedList( data, 0, outerLen, dim, true ),\r\n\t\t\t\ttriangles = [];\r\n\r\n\t\t\tif ( ! outerNode || outerNode.next === outerNode.prev ) { return triangles; }\r\n\r\n\t\t\tvar minX, minY, maxX, maxY, x, y, invSize;\r\n\r\n\t\t\tif ( hasHoles ) { outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); }\r\n\r\n\t\t\t// if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\r\n\t\t\tif ( data.length > 80 * dim ) {\r\n\r\n\t\t\t\tminX = maxX = data[ 0 ];\r\n\t\t\t\tminY = maxY = data[ 1 ];\r\n\r\n\t\t\t\tfor ( var i = dim; i < outerLen; i += dim ) {\r\n\r\n\t\t\t\t\tx = data[ i ];\r\n\t\t\t\t\ty = data[ i + 1 ];\r\n\t\t\t\t\tif ( x < minX ) { minX = x; }\r\n\t\t\t\t\tif ( y < minY ) { minY = y; }\r\n\t\t\t\t\tif ( x > maxX ) { maxX = x; }\r\n\t\t\t\t\tif ( y > maxY ) { maxY = y; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// minX, minY and invSize are later used to transform coords into integers for z-order calculation\r\n\t\t\t\tinvSize = Math.max( maxX - minX, maxY - minY );\r\n\t\t\t\tinvSize = invSize !== 0 ? 1 / invSize : 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tearcutLinked( outerNode, triangles, dim, minX, minY, invSize );\r\n\r\n\t\t\treturn triangles;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t// create a circular doubly linked list from polygon points in the specified winding order\r\n\tfunction linkedList( data, start, end, dim, clockwise ) {\r\n\r\n\t\tvar i, last;\r\n\r\n\t\tif ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {\r\n\r\n\t\t\tfor ( i = start; i < end; i += dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); }\r\n\r\n\t\t} else {\r\n\r\n\t\t\tfor ( i = end - dim; i >= start; i -= dim ) { last = insertNode( i, data[ i ], data[ i + 1 ], last ); }\r\n\r\n\t\t}\r\n\r\n\t\tif ( last && equals( last, last.next ) ) {\r\n\r\n\t\t\tremoveNode( last );\r\n\t\t\tlast = last.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn last;\r\n\r\n\t}\r\n\r\n\t// eliminate colinear or duplicate points\r\n\tfunction filterPoints( start, end ) {\r\n\r\n\t\tif ( ! start ) { return start; }\r\n\t\tif ( ! end ) { end = start; }\r\n\r\n\t\tvar p = start,\r\n\t\t\tagain;\r\n\t\tdo {\r\n\r\n\t\t\tagain = false;\r\n\r\n\t\t\tif ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) {\r\n\r\n\t\t\t\tremoveNode( p );\r\n\t\t\t\tp = end = p.prev;\r\n\t\t\t\tif ( p === p.next ) { break; }\r\n\t\t\t\tagain = true;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tp = p.next;\r\n\r\n\t\t\t}\r\n\r\n\t\t} while ( again || p !== end );\r\n\r\n\t\treturn end;\r\n\r\n\t}\r\n\r\n\t// main ear slicing loop which triangulates a polygon (given as a linked list)\r\n\tfunction earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {\r\n\r\n\t\tif ( ! ear ) { return; }\r\n\r\n\t\t// interlink polygon nodes in z-order\r\n\t\tif ( ! pass && invSize ) { indexCurve( ear, minX, minY, invSize ); }\r\n\r\n\t\tvar stop = ear,\r\n\t\t\tprev, next;\r\n\r\n\t\t// iterate through ears, slicing them one by one\r\n\t\twhile ( ear.prev !== ear.next ) {\r\n\r\n\t\t\tprev = ear.prev;\r\n\t\t\tnext = ear.next;\r\n\r\n\t\t\tif ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {\r\n\r\n\t\t\t\t// cut off the triangle\r\n\t\t\t\ttriangles.push( prev.i / dim );\r\n\t\t\t\ttriangles.push( ear.i / dim );\r\n\t\t\t\ttriangles.push( next.i / dim );\r\n\r\n\t\t\t\tremoveNode( ear );\r\n\r\n\t\t\t\t// skipping the next vertex leads to less sliver triangles\r\n\t\t\t\tear = next.next;\r\n\t\t\t\tstop = next.next;\r\n\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tear = next;\r\n\r\n\t\t\t// if we looped through the whole remaining polygon and can't find any more ears\r\n\t\t\tif ( ear === stop ) {\r\n\r\n\t\t\t\t// try filtering points and slicing again\r\n\t\t\t\tif ( ! pass ) {\r\n\r\n\t\t\t\t\tearcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );\r\n\r\n\t\t\t\t\t// if this didn't work, try curing all small self-intersections locally\r\n\r\n\t\t\t\t} else if ( pass === 1 ) {\r\n\r\n\t\t\t\t\tear = cureLocalIntersections( ear, triangles, dim );\r\n\t\t\t\t\tearcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );\r\n\r\n\t\t\t\t\t// as a last resort, try splitting the remaining polygon into two\r\n\r\n\t\t\t\t} else if ( pass === 2 ) {\r\n\r\n\t\t\t\t\tsplitEarcut( ear, triangles, dim, minX, minY, invSize );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// check whether a polygon node forms a valid ear with adjacent nodes\r\n\tfunction isEar( ear ) {\r\n\r\n\t\tvar a = ear.prev,\r\n\t\t\tb = ear,\r\n\t\t\tc = ear.next;\r\n\r\n\t\tif ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear\r\n\r\n\t\t// now make sure we don't have other points inside the potential ear\r\n\t\tvar p = ear.next.next;\r\n\r\n\t\twhile ( p !== ear.prev ) {\r\n\r\n\t\t\tif ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\tfunction isEarHashed( ear, minX, minY, invSize ) {\r\n\r\n\t\tvar a = ear.prev,\r\n\t\t\tb = ear,\r\n\t\t\tc = ear.next;\r\n\r\n\t\tif ( area( a, b, c ) >= 0 ) { return false; } // reflex, can't be an ear\r\n\r\n\t\t// triangle bbox; min & max are calculated like this for speed\r\n\t\tvar minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ),\r\n\t\t\tminTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ),\r\n\t\t\tmaxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ),\r\n\t\t\tmaxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y );\r\n\r\n\t\t// z-order range for the current triangle bbox;\r\n\t\tvar minZ = zOrder( minTX, minTY, minX, minY, invSize ),\r\n\t\t\tmaxZ = zOrder( maxTX, maxTY, minX, minY, invSize );\r\n\r\n\t\tvar p = ear.prevZ,\r\n\t\t\tn = ear.nextZ;\r\n\r\n\t\t// look for points inside the triangle in both directions\r\n\t\twhile ( p && p.z >= minZ && n && n.z <= maxZ ) {\r\n\r\n\t\t\tif ( p !== ear.prev && p !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.prevZ;\r\n\r\n\t\t\tif ( n !== ear.prev && n !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&\r\n\t\t\t\tarea( n.prev, n, n.next ) >= 0 ) { return false; }\r\n\t\t\tn = n.nextZ;\r\n\r\n\t\t}\r\n\r\n\t\t// look for remaining points in decreasing z-order\r\n\t\twhile ( p && p.z >= minZ ) {\r\n\r\n\t\t\tif ( p !== ear.prev && p !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) &&\r\n\t\t\t\tarea( p.prev, p, p.next ) >= 0 ) { return false; }\r\n\t\t\tp = p.prevZ;\r\n\r\n\t\t}\r\n\r\n\t\t// look for remaining points in increasing z-order\r\n\t\twhile ( n && n.z <= maxZ ) {\r\n\r\n\t\t\tif ( n !== ear.prev && n !== ear.next &&\r\n\t\t\t\tpointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y ) &&\r\n\t\t\t\tarea( n.prev, n, n.next ) >= 0 ) { return false; }\r\n\t\t\tn = n.nextZ;\r\n\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\r\n\t}\r\n\r\n\t// go through all polygon nodes and cure small local self-intersections\r\n\tfunction cureLocalIntersections( start, triangles, dim ) {\r\n\r\n\t\tvar p = start;\r\n\t\tdo {\r\n\r\n\t\t\tvar a = p.prev,\r\n\t\t\t\tb = p.next.next;\r\n\r\n\t\t\tif ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) {\r\n\r\n\t\t\t\ttriangles.push( a.i / dim );\r\n\t\t\t\ttriangles.push( p.i / dim );\r\n\t\t\t\ttriangles.push( b.i / dim );\r\n\r\n\t\t\t\t// remove two nodes involved\r\n\t\t\t\tremoveNode( p );\r\n\t\t\t\tremoveNode( p.next );\r\n\r\n\t\t\t\tp = start = b;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\t// try splitting polygon into two and triangulate them independently\r\n\tfunction splitEarcut( start, triangles, dim, minX, minY, invSize ) {\r\n\r\n\t\t// look for a valid diagonal that divides the polygon into two\r\n\t\tvar a = start;\r\n\t\tdo {\r\n\r\n\t\t\tvar b = a.next.next;\r\n\t\t\twhile ( b !== a.prev ) {\r\n\r\n\t\t\t\tif ( a.i !== b.i && isValidDiagonal( a, b ) ) {\r\n\r\n\t\t\t\t\t// split the polygon in two by the diagonal\r\n\t\t\t\t\tvar c = splitPolygon( a, b );\r\n\r\n\t\t\t\t\t// filter colinear points around the cuts\r\n\t\t\t\t\ta = filterPoints( a, a.next );\r\n\t\t\t\t\tc = filterPoints( c, c.next );\r\n\r\n\t\t\t\t\t// run earcut on each half\r\n\t\t\t\t\tearcutLinked( a, triangles, dim, minX, minY, invSize );\r\n\t\t\t\t\tearcutLinked( c, triangles, dim, minX, minY, invSize );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tb = b.next;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ta = a.next;\r\n\r\n\t\t} while ( a !== start );\r\n\r\n\t}\r\n\r\n\t// link every hole into the outer loop, producing a single-ring polygon without holes\r\n\tfunction eliminateHoles( data, holeIndices, outerNode, dim ) {\r\n\r\n\t\tvar queue = [],\r\n\t\t\ti, len, start, end, list;\r\n\r\n\t\tfor ( i = 0, len = holeIndices.length; i < len; i ++ ) {\r\n\r\n\t\t\tstart = holeIndices[ i ] * dim;\r\n\t\t\tend = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length;\r\n\t\t\tlist = linkedList( data, start, end, dim, false );\r\n\t\t\tif ( list === list.next ) { list.steiner = true; }\r\n\t\t\tqueue.push( getLeftmost( list ) );\r\n\r\n\t\t}\r\n\r\n\t\tqueue.sort( compareX );\r\n\r\n\t\t// process holes from left to right\r\n\t\tfor ( i = 0; i < queue.length; i ++ ) {\r\n\r\n\t\t\teliminateHole( queue[ i ], outerNode );\r\n\t\t\touterNode = filterPoints( outerNode, outerNode.next );\r\n\r\n\t\t}\r\n\r\n\t\treturn outerNode;\r\n\r\n\t}\r\n\r\n\tfunction compareX( a, b ) {\r\n\r\n\t\treturn a.x - b.x;\r\n\r\n\t}\r\n\r\n\t// find a bridge between vertices that connects hole with an outer ring and and link it\r\n\tfunction eliminateHole( hole, outerNode ) {\r\n\r\n\t\touterNode = findHoleBridge( hole, outerNode );\r\n\t\tif ( outerNode ) {\r\n\r\n\t\t\tvar b = splitPolygon( outerNode, hole );\r\n\t\t\tfilterPoints( b, b.next );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t// David Eberly's algorithm for finding a bridge between hole and outer polygon\r\n\tfunction findHoleBridge( hole, outerNode ) {\r\n\r\n\t\tvar p = outerNode,\r\n\t\t\thx = hole.x,\r\n\t\t\thy = hole.y,\r\n\t\t\tqx = - Infinity,\r\n\t\t\tm;\r\n\r\n\t\t// find a segment intersected by a ray from the hole's leftmost point to the left;\r\n\t\t// segment's endpoint with lesser x will be potential connection point\r\n\t\tdo {\r\n\r\n\t\t\tif ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) {\r\n\r\n\t\t\t\tvar x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y );\r\n\t\t\t\tif ( x <= hx && x > qx ) {\r\n\r\n\t\t\t\t\tqx = x;\r\n\t\t\t\t\tif ( x === hx ) {\r\n\r\n\t\t\t\t\t\tif ( hy === p.y ) { return p; }\r\n\t\t\t\t\t\tif ( hy === p.next.y ) { return p.next; }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tm = p.x < p.next.x ? p : p.next;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== outerNode );\r\n\r\n\t\tif ( ! m ) { return null; }\r\n\r\n\t\tif ( hx === qx ) { return m.prev; } // hole touches outer segment; pick lower endpoint\r\n\r\n\t\t// look for points inside the triangle of hole point, segment intersection and endpoint;\r\n\t\t// if there are no points found, we have a valid connection;\r\n\t\t// otherwise choose the point of the minimum angle with the ray as connection point\r\n\r\n\t\tvar stop = m,\r\n\t\t\tmx = m.x,\r\n\t\t\tmy = m.y,\r\n\t\t\ttanMin = Infinity,\r\n\t\t\ttan;\r\n\r\n\t\tp = m.next;\r\n\r\n\t\twhile ( p !== stop ) {\r\n\r\n\t\t\tif ( hx >= p.x && p.x >= mx && hx !== p.x &&\r\n\t\t\t\t\tpointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) {\r\n\r\n\t\t\t\ttan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential\r\n\r\n\t\t\t\tif ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) {\r\n\r\n\t\t\t\t\tm = p;\r\n\t\t\t\t\ttanMin = tan;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tp = p.next;\r\n\r\n\t\t}\r\n\r\n\t\treturn m;\r\n\r\n\t}\r\n\r\n\t// interlink polygon nodes in z-order\r\n\tfunction indexCurve( start, minX, minY, invSize ) {\r\n\r\n\t\tvar p = start;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.z === null ) { p.z = zOrder( p.x, p.y, minX, minY, invSize ); }\r\n\t\t\tp.prevZ = p.prev;\r\n\t\t\tp.nextZ = p.next;\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\tp.prevZ.nextZ = null;\r\n\t\tp.prevZ = null;\r\n\r\n\t\tsortLinked( p );\r\n\r\n\t}\r\n\r\n\t// Simon Tatham's linked list merge sort algorithm\r\n\t// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\r\n\tfunction sortLinked( list ) {\r\n\r\n\t\tvar i, p, q, e, tail, numMerges, pSize, qSize,\r\n\t\t\tinSize = 1;\r\n\r\n\t\tdo {\r\n\r\n\t\t\tp = list;\r\n\t\t\tlist = null;\r\n\t\t\ttail = null;\r\n\t\t\tnumMerges = 0;\r\n\r\n\t\t\twhile ( p ) {\r\n\r\n\t\t\t\tnumMerges ++;\r\n\t\t\t\tq = p;\r\n\t\t\t\tpSize = 0;\r\n\t\t\t\tfor ( i = 0; i < inSize; i ++ ) {\r\n\r\n\t\t\t\t\tpSize ++;\r\n\t\t\t\t\tq = q.nextZ;\r\n\t\t\t\t\tif ( ! q ) { break; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tqSize = inSize;\r\n\r\n\t\t\t\twhile ( pSize > 0 || ( qSize > 0 && q ) ) {\r\n\r\n\t\t\t\t\tif ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) {\r\n\r\n\t\t\t\t\t\te = p;\r\n\t\t\t\t\t\tp = p.nextZ;\r\n\t\t\t\t\t\tpSize --;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\te = q;\r\n\t\t\t\t\t\tq = q.nextZ;\r\n\t\t\t\t\t\tqSize --;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( tail ) { tail.nextZ = e; }\r\n\t\t\t\t\telse { list = e; }\r\n\r\n\t\t\t\t\te.prevZ = tail;\r\n\t\t\t\t\ttail = e;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tp = q;\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttail.nextZ = null;\r\n\t\t\tinSize *= 2;\r\n\r\n\t\t} while ( numMerges > 1 );\r\n\r\n\t\treturn list;\r\n\r\n\t}\r\n\r\n\t// z-order of a point given coords and inverse of the longer side of data bbox\r\n\tfunction zOrder( x, y, minX, minY, invSize ) {\r\n\r\n\t\t// coords are transformed into non-negative 15-bit integer range\r\n\t\tx = 32767 * ( x - minX ) * invSize;\r\n\t\ty = 32767 * ( y - minY ) * invSize;\r\n\r\n\t\tx = ( x | ( x << 8 ) ) & 0x00FF00FF;\r\n\t\tx = ( x | ( x << 4 ) ) & 0x0F0F0F0F;\r\n\t\tx = ( x | ( x << 2 ) ) & 0x33333333;\r\n\t\tx = ( x | ( x << 1 ) ) & 0x55555555;\r\n\r\n\t\ty = ( y | ( y << 8 ) ) & 0x00FF00FF;\r\n\t\ty = ( y | ( y << 4 ) ) & 0x0F0F0F0F;\r\n\t\ty = ( y | ( y << 2 ) ) & 0x33333333;\r\n\t\ty = ( y | ( y << 1 ) ) & 0x55555555;\r\n\r\n\t\treturn x | ( y << 1 );\r\n\r\n\t}\r\n\r\n\t// find the leftmost node of a polygon ring\r\n\tfunction getLeftmost( start ) {\r\n\r\n\t\tvar p = start,\r\n\t\t\tleftmost = start;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) { leftmost = p; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== start );\r\n\r\n\t\treturn leftmost;\r\n\r\n\t}\r\n\r\n\t// check if a point lies within a convex triangle\r\n\tfunction pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {\r\n\r\n\t\treturn ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 &&\r\n\t\t\t ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 &&\r\n\t\t\t ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0;\r\n\r\n\t}\r\n\r\n\t// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\r\n\tfunction isValidDiagonal( a, b ) {\r\n\r\n\t\treturn a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) &&\r\n\t\t\t locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b );\r\n\r\n\t}\r\n\r\n\t// signed area of a triangle\r\n\tfunction area( p, q, r ) {\r\n\r\n\t\treturn ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y );\r\n\r\n\t}\r\n\r\n\t// check if two points are equal\r\n\tfunction equals( p1, p2 ) {\r\n\r\n\t\treturn p1.x === p2.x && p1.y === p2.y;\r\n\r\n\t}\r\n\r\n\t// check if two segments intersect\r\n\tfunction intersects( p1, q1, p2, q2 ) {\r\n\r\n\t\tif ( ( equals( p1, p2 ) && equals( q1, q2 ) ) ||\r\n\t\t\t( equals( p1, q2 ) && equals( p2, q1 ) ) ) { return true; }\r\n\t\treturn area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 &&\r\n\t\t\t area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0;\r\n\r\n\t}\r\n\r\n\t// check if a polygon diagonal intersects any polygon segments\r\n\tfunction intersectsPolygon( a, b ) {\r\n\r\n\t\tvar p = a;\r\n\t\tdo {\r\n\r\n\t\t\tif ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\r\n\t\t\t\t\tintersects( p, p.next, a, b ) ) { return true; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== a );\r\n\r\n\t\treturn false;\r\n\r\n\t}\r\n\r\n\t// check if a polygon diagonal is locally inside the polygon\r\n\tfunction locallyInside( a, b ) {\r\n\r\n\t\treturn area( a.prev, a, a.next ) < 0 ?\r\n\t\t\tarea( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 :\r\n\t\t\tarea( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0;\r\n\r\n\t}\r\n\r\n\t// check if the middle point of a polygon diagonal is inside the polygon\r\n\tfunction middleInside( a, b ) {\r\n\r\n\t\tvar p = a,\r\n\t\t\tinside = false,\r\n\t\t\tpx = ( a.x + b.x ) / 2,\r\n\t\t\tpy = ( a.y + b.y ) / 2;\r\n\t\tdo {\r\n\r\n\t\t\tif ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y &&\r\n\t\t\t\t\t( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) )\r\n\t\t\t\t{ inside = ! inside; }\r\n\t\t\tp = p.next;\r\n\r\n\t\t} while ( p !== a );\r\n\r\n\t\treturn inside;\r\n\r\n\t}\r\n\r\n\t// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\r\n\t// if one belongs to the outer ring and another to a hole, it merges it into a single ring\r\n\tfunction splitPolygon( a, b ) {\r\n\r\n\t\tvar a2 = new Node( a.i, a.x, a.y ),\r\n\t\t\tb2 = new Node( b.i, b.x, b.y ),\r\n\t\t\tan = a.next,\r\n\t\t\tbp = b.prev;\r\n\r\n\t\ta.next = b;\r\n\t\tb.prev = a;\r\n\r\n\t\ta2.next = an;\r\n\t\tan.prev = a2;\r\n\r\n\t\tb2.next = a2;\r\n\t\ta2.prev = b2;\r\n\r\n\t\tbp.next = b2;\r\n\t\tb2.prev = bp;\r\n\r\n\t\treturn b2;\r\n\r\n\t}\r\n\r\n\t// create a node and optionally link it with previous one (in a circular doubly linked list)\r\n\tfunction insertNode( i, x, y, last ) {\r\n\r\n\t\tvar p = new Node( i, x, y );\r\n\r\n\t\tif ( ! last ) {\r\n\r\n\t\t\tp.prev = p;\r\n\t\t\tp.next = p;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tp.next = last.next;\r\n\t\t\tp.prev = last;\r\n\t\t\tlast.next.prev = p;\r\n\t\t\tlast.next = p;\r\n\r\n\t\t}\r\n\r\n\t\treturn p;\r\n\r\n\t}\r\n\r\n\tfunction removeNode( p ) {\r\n\r\n\t\tp.next.prev = p.prev;\r\n\t\tp.prev.next = p.next;\r\n\r\n\t\tif ( p.prevZ ) { p.prevZ.nextZ = p.nextZ; }\r\n\t\tif ( p.nextZ ) { p.nextZ.prevZ = p.prevZ; }\r\n\r\n\t}\r\n\r\n\tfunction Node( i, x, y ) {\r\n\r\n\t\t// vertex index in coordinates array\r\n\t\tthis.i = i;\r\n\r\n\t\t// vertex coordinates\r\n\t\tthis.x = x;\r\n\t\tthis.y = y;\r\n\r\n\t\t// previous and next vertex nodes in a polygon ring\r\n\t\tthis.prev = null;\r\n\t\tthis.next = null;\r\n\r\n\t\t// z-order curve value\r\n\t\tthis.z = null;\r\n\r\n\t\t// previous and next nodes in z-order\r\n\t\tthis.prevZ = null;\r\n\t\tthis.nextZ = null;\r\n\r\n\t\t// indicates whether this is a steiner point\r\n\t\tthis.steiner = false;\r\n\r\n\t}\r\n\r\n\tfunction signedArea( data, start, end, dim ) {\r\n\r\n\t\tvar sum = 0;\r\n\t\tfor ( var i = start, j = end - dim; i < end; i += dim ) {\r\n\r\n\t\t\tsum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] );\r\n\t\t\tj = i;\r\n\r\n\t\t}\r\n\r\n\t\treturn sum;\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t */\r\n\r\n\tvar ShapeUtils = {\r\n\r\n\t\t// calculate area of the contour polygon\r\n\r\n\t\tarea: function ( contour ) {\r\n\r\n\t\t\tvar n = contour.length;\r\n\t\t\tvar a = 0.0;\r\n\r\n\t\t\tfor ( var p = n - 1, q = 0; q < n; p = q ++ ) {\r\n\r\n\t\t\t\ta += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn a * 0.5;\r\n\r\n\t\t},\r\n\r\n\t\tisClockWise: function ( pts ) {\r\n\r\n\t\t\treturn ShapeUtils.area( pts ) < 0;\r\n\r\n\t\t},\r\n\r\n\t\ttriangulateShape: function ( contour, holes ) {\r\n\r\n\t\t\tvar vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ]\r\n\t\t\tvar holeIndices = []; // array of hole indices\r\n\t\t\tvar faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ]\r\n\r\n\t\t\tremoveDupEndPts( contour );\r\n\t\t\taddContour( vertices, contour );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar holeIndex = contour.length;\r\n\r\n\t\t\tholes.forEach( removeDupEndPts );\r\n\r\n\t\t\tfor ( var i = 0; i < holes.length; i ++ ) {\r\n\r\n\t\t\t\tholeIndices.push( holeIndex );\r\n\t\t\t\tholeIndex += holes[ i ].length;\r\n\t\t\t\taddContour( vertices, holes[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar triangles = Earcut.triangulate( vertices, holeIndices );\r\n\r\n\t\t\t//\r\n\r\n\t\t\tfor ( var i = 0; i < triangles.length; i += 3 ) {\r\n\r\n\t\t\t\tfaces.push( triangles.slice( i, i + 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn faces;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tfunction removeDupEndPts( points ) {\r\n\r\n\t\tvar l = points.length;\r\n\r\n\t\tif ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) {\r\n\r\n\t\t\tpoints.pop();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction addContour( vertices, contour ) {\r\n\r\n\t\tfor ( var i = 0; i < contour.length; i ++ ) {\r\n\r\n\t\t\tvertices.push( contour[ i ].x );\r\n\t\t\tvertices.push( contour[ i ].y );\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t * Creates extruded geometry from a path shape.\r\n\t *\r\n\t * parameters = {\r\n\t *\r\n\t * curveSegments: , // number of points on the curves\r\n\t * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too\r\n\t * depth: , // Depth to extrude the shape\r\n\t *\r\n\t * bevelEnabled: , // turn on bevel\r\n\t * bevelThickness: , // how deep into the original shape bevel goes\r\n\t * bevelSize: , // how far from shape outline (including bevelOffset) is bevel\r\n\t * bevelOffset: , // how far from shape outline does bevel start\r\n\t * bevelSegments: , // number of bevel layers\r\n\t *\r\n\t * extrudePath: // curve to extrude shape along\r\n\t *\r\n\t * UVGenerator: // object that provides UV generator functions\r\n\t *\r\n\t * }\r\n\t */\r\n\r\n\t// ExtrudeGeometry\r\n\r\n\tfunction ExtrudeGeometry( shapes, options ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ExtrudeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\toptions: options\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tExtrudeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tExtrudeGeometry.prototype.constructor = ExtrudeGeometry;\r\n\r\n\tExtrudeGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Geometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\t\tvar options = this.parameters.options;\r\n\r\n\t\treturn toJSON( shapes, options, data );\r\n\r\n\t};\r\n\r\n\t// ExtrudeBufferGeometry\r\n\r\n\tfunction ExtrudeBufferGeometry( shapes, options ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ExtrudeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\toptions: options\r\n\t\t};\r\n\r\n\t\tshapes = Array.isArray( shapes ) ? shapes : [ shapes ];\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar verticesArray = [];\r\n\t\tvar uvArray = [];\r\n\r\n\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar shape = shapes[ i ];\r\n\t\t\taddShape( shape );\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) );\r\n\r\n\t\tthis.computeVertexNormals();\r\n\r\n\t\t// functions\r\n\r\n\t\tfunction addShape( shape ) {\r\n\r\n\t\t\tvar placeholder = [];\r\n\r\n\t\t\t// options\r\n\r\n\t\t\tvar curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;\r\n\t\t\tvar steps = options.steps !== undefined ? options.steps : 1;\r\n\t\t\tvar depth = options.depth !== undefined ? options.depth : 100;\r\n\r\n\t\t\tvar bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;\r\n\t\t\tvar bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;\r\n\t\t\tvar bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;\r\n\t\t\tvar bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0;\r\n\t\t\tvar bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;\r\n\r\n\t\t\tvar extrudePath = options.extrudePath;\r\n\r\n\t\t\tvar uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator;\r\n\r\n\t\t\t// deprecated options\r\n\r\n\t\t\tif ( options.amount !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' );\r\n\t\t\t\tdepth = options.amount;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//\r\n\r\n\t\t\tvar extrudePts, extrudeByPath = false;\r\n\t\t\tvar splineTube, binormal, normal, position2;\r\n\r\n\t\t\tif ( extrudePath ) {\r\n\r\n\t\t\t\textrudePts = extrudePath.getSpacedPoints( steps );\r\n\r\n\t\t\t\textrudeByPath = true;\r\n\t\t\t\tbevelEnabled = false; // bevels not supported for path extrusion\r\n\r\n\t\t\t\t// SETUP TNB variables\r\n\r\n\t\t\t\t// TODO1 - have a .isClosed in spline?\r\n\r\n\t\t\t\tsplineTube = extrudePath.computeFrenetFrames( steps, false );\r\n\r\n\t\t\t\t// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);\r\n\r\n\t\t\t\tbinormal = new Vector3();\r\n\t\t\t\tnormal = new Vector3();\r\n\t\t\t\tposition2 = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Safeguards if bevels are not enabled\r\n\r\n\t\t\tif ( ! bevelEnabled ) {\r\n\r\n\t\t\t\tbevelSegments = 0;\r\n\t\t\t\tbevelThickness = 0;\r\n\t\t\t\tbevelSize = 0;\r\n\t\t\t\tbevelOffset = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Variables initialization\r\n\r\n\t\t\tvar ahole, h, hl; // looping of holes\r\n\r\n\t\t\tvar shapePoints = shape.extractPoints( curveSegments );\r\n\r\n\t\t\tvar vertices = shapePoints.shape;\r\n\t\t\tvar holes = shapePoints.holes;\r\n\r\n\t\t\tvar reverse = ! ShapeUtils.isClockWise( vertices );\r\n\r\n\t\t\tif ( reverse ) {\r\n\r\n\t\t\t\tvertices = vertices.reverse();\r\n\r\n\t\t\t\t// Maybe we should also check if holes are in the opposite direction, just to be safe ...\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\t\tif ( ShapeUtils.isClockWise( ahole ) ) {\r\n\r\n\t\t\t\t\t\tholes[ h ] = ahole.reverse();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar faces = ShapeUtils.triangulateShape( vertices, holes );\r\n\r\n\t\t\t/* Vertices */\r\n\r\n\t\t\tvar contour = vertices; // vertices has all points but contour has only points of circumference\r\n\r\n\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\tvertices = vertices.concat( ahole );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction scalePt2( pt, vec, size ) {\r\n\r\n\t\t\t\tif ( ! vec ) { console.error( \"THREE.ExtrudeGeometry: vec does not exist\" ); }\r\n\r\n\t\t\t\treturn vec.clone().multiplyScalar( size ).add( pt );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar b, bs, t, z,\r\n\t\t\t\tvert, vlen = vertices.length,\r\n\t\t\t\tface, flen = faces.length;\r\n\r\n\r\n\t\t\t// Find directions for point movement\r\n\r\n\r\n\t\t\tfunction getBevelVec( inPt, inPrev, inNext ) {\r\n\r\n\t\t\t\t// computes for inPt the corresponding point inPt' on a new contour\r\n\t\t\t\t// shifted by 1 unit (length of normalized vector) to the left\r\n\t\t\t\t// if we walk along contour clockwise, this new contour is outside the old one\r\n\t\t\t\t//\r\n\t\t\t\t// inPt' is the intersection of the two lines parallel to the two\r\n\t\t\t\t// adjacent edges of inPt at a distance of 1 unit on the left side.\r\n\r\n\t\t\t\tvar v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt\r\n\r\n\t\t\t\t// good reading for geometry algorithms (here: line-line intersection)\r\n\t\t\t\t// http://geomalgorithms.com/a05-_intersect-1.html\r\n\r\n\t\t\t\tvar v_prev_x = inPt.x - inPrev.x,\r\n\t\t\t\t\tv_prev_y = inPt.y - inPrev.y;\r\n\t\t\t\tvar v_next_x = inNext.x - inPt.x,\r\n\t\t\t\t\tv_next_y = inNext.y - inPt.y;\r\n\r\n\t\t\t\tvar v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );\r\n\r\n\t\t\t\t// check for collinear edges\r\n\t\t\t\tvar collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );\r\n\r\n\t\t\t\tif ( Math.abs( collinear0 ) > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t// not collinear\r\n\r\n\t\t\t\t\t// length of vectors for normalizing\r\n\r\n\t\t\t\t\tvar v_prev_len = Math.sqrt( v_prev_lensq );\r\n\t\t\t\t\tvar v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );\r\n\r\n\t\t\t\t\t// shift adjacent points by unit vectors to the left\r\n\r\n\t\t\t\t\tvar ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );\r\n\t\t\t\t\tvar ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );\r\n\r\n\t\t\t\t\tvar ptNextShift_x = ( inNext.x - v_next_y / v_next_len );\r\n\t\t\t\t\tvar ptNextShift_y = ( inNext.y + v_next_x / v_next_len );\r\n\r\n\t\t\t\t\t// scaling factor for v_prev to intersection point\r\n\r\n\t\t\t\t\tvar sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -\r\n\t\t\t\t\t\t\t( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /\r\n\t\t\t\t\t\t( v_prev_x * v_next_y - v_prev_y * v_next_x );\r\n\r\n\t\t\t\t\t// vector from inPt to intersection point\r\n\r\n\t\t\t\t\tv_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );\r\n\t\t\t\t\tv_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );\r\n\r\n\t\t\t\t\t// Don't normalize!, otherwise sharp corners become ugly\r\n\t\t\t\t\t// but prevent crazy spikes\r\n\t\t\t\t\tvar v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );\r\n\t\t\t\t\tif ( v_trans_lensq <= 2 ) {\r\n\r\n\t\t\t\t\t\treturn new Vector2( v_trans_x, v_trans_y );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_trans_lensq / 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// handle special case of collinear edges\r\n\r\n\t\t\t\t\tvar direction_eq = false; // assumes: opposite\r\n\t\t\t\t\tif ( v_prev_x > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\tif ( v_next_x > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( v_prev_x < - Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\tif ( v_next_x < - Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tif ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) {\r\n\r\n\t\t\t\t\t\t\t\tdirection_eq = true;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( direction_eq ) {\r\n\r\n\t\t\t\t\t\t// console.log(\"Warning: lines are a straight sequence\");\r\n\t\t\t\t\t\tv_trans_x = - v_prev_y;\r\n\t\t\t\t\t\tv_trans_y = v_prev_x;\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_prev_lensq );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// console.log(\"Warning: lines are a straight spike\");\r\n\t\t\t\t\t\tv_trans_x = v_prev_x;\r\n\t\t\t\t\t\tv_trans_y = v_prev_y;\r\n\t\t\t\t\t\tshrink_by = Math.sqrt( v_prev_lensq / 2 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tvar contourMovements = [];\r\n\r\n\t\t\tfor ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {\r\n\r\n\t\t\t\tif ( j === il ) { j = 0; }\r\n\t\t\t\tif ( k === il ) { k = 0; }\r\n\r\n\t\t\t\t// (j)---(i)---(k)\r\n\t\t\t\t// console.log('i,j,k', i, j , k)\r\n\r\n\t\t\t\tcontourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar holesMovements = [],\r\n\t\t\t\toneHoleMovements, verticesMovements = contourMovements.concat();\r\n\r\n\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\tahole = holes[ h ];\r\n\r\n\t\t\t\toneHoleMovements = [];\r\n\r\n\t\t\t\tfor ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {\r\n\r\n\t\t\t\t\tif ( j === il ) { j = 0; }\r\n\t\t\t\t\tif ( k === il ) { k = 0; }\r\n\r\n\t\t\t\t\t// (j)---(i)---(k)\r\n\t\t\t\t\toneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tholesMovements.push( oneHoleMovements );\r\n\t\t\t\tverticesMovements = verticesMovements.concat( oneHoleMovements );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Loop bevelSegments, 1 for the front, 1 for the back\r\n\r\n\t\t\tfor ( b = 0; b < bevelSegments; b ++ ) {\r\n\r\n\t\t\t\t//for ( b = bevelSegments; b > 0; b -- ) {\r\n\r\n\t\t\t\tt = b / bevelSegments;\r\n\t\t\t\tz = bevelThickness * Math.cos( t * Math.PI / 2 );\r\n\t\t\t\tbs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;\r\n\r\n\t\t\t\t// contract shape\r\n\r\n\t\t\t\tfor ( i = 0, il = contour.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvert = scalePt2( contour[ i ], contourMovements[ i ], bs );\r\n\r\n\t\t\t\t\tv( vert.x, vert.y, - z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// expand holes\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\toneHoleMovements = holesMovements[ h ];\r\n\r\n\t\t\t\t\tfor ( i = 0, il = ahole.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );\r\n\r\n\t\t\t\t\t\tv( vert.x, vert.y, - z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbs = bevelSize + bevelOffset;\r\n\r\n\t\t\t// Back facing vertices\r\n\r\n\t\t\tfor ( i = 0; i < vlen; i ++ ) {\r\n\r\n\t\t\t\tvert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];\r\n\r\n\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\tv( vert.x, vert.y, 0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );\r\n\r\n\t\t\t\t\tnormal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );\r\n\t\t\t\t\tbinormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );\r\n\r\n\t\t\t\t\tposition2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal );\r\n\r\n\t\t\t\t\tv( position2.x, position2.y, position2.z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Add stepped vertices...\r\n\t\t\t// Including front facing vertices\r\n\r\n\t\t\tvar s;\r\n\r\n\t\t\tfor ( s = 1; s <= steps; s ++ ) {\r\n\r\n\t\t\t\tfor ( i = 0; i < vlen; i ++ ) {\r\n\r\n\t\t\t\t\tvert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];\r\n\r\n\t\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\t\tv( vert.x, vert.y, depth / steps * s );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );\r\n\r\n\t\t\t\t\t\tnormal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x );\r\n\t\t\t\t\t\tbinormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y );\r\n\r\n\t\t\t\t\t\tposition2.copy( extrudePts[ s ] ).add( normal ).add( binormal );\r\n\r\n\t\t\t\t\t\tv( position2.x, position2.y, position2.z );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\t// Add bevel segments planes\r\n\r\n\t\t\t//for ( b = 1; b <= bevelSegments; b ++ ) {\r\n\t\t\tfor ( b = bevelSegments - 1; b >= 0; b -- ) {\r\n\r\n\t\t\t\tt = b / bevelSegments;\r\n\t\t\t\tz = bevelThickness * Math.cos( t * Math.PI / 2 );\r\n\t\t\t\tbs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset;\r\n\r\n\t\t\t\t// contract shape\r\n\r\n\t\t\t\tfor ( i = 0, il = contour.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvert = scalePt2( contour[ i ], contourMovements[ i ], bs );\r\n\t\t\t\t\tv( vert.x, vert.y, depth + z );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// expand holes\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\toneHoleMovements = holesMovements[ h ];\r\n\r\n\t\t\t\t\tfor ( i = 0, il = ahole.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );\r\n\r\n\t\t\t\t\t\tif ( ! extrudeByPath ) {\r\n\r\n\t\t\t\t\t\t\tv( vert.x, vert.y, depth + z );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tv( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t/* Faces */\r\n\r\n\t\t\t// Top and bottom faces\r\n\r\n\t\t\tbuildLidFaces();\r\n\r\n\t\t\t// Sides faces\r\n\r\n\t\t\tbuildSideFaces();\r\n\r\n\r\n\t\t\t///// Internal functions\r\n\r\n\t\t\tfunction buildLidFaces() {\r\n\r\n\t\t\t\tvar start = verticesArray.length / 3;\r\n\r\n\t\t\t\tif ( bevelEnabled ) {\r\n\r\n\t\t\t\t\tvar layer = 0; // steps + 1\r\n\t\t\t\t\tvar offset = vlen * layer;\r\n\r\n\t\t\t\t\t// Bottom faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tlayer = steps + bevelSegments * 2;\r\n\t\t\t\t\toffset = vlen * layer;\r\n\r\n\t\t\t\t\t// Top faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// Bottom faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 2 ], face[ 1 ], face[ 0 ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Top faces\r\n\r\n\t\t\t\t\tfor ( i = 0; i < flen; i ++ ) {\r\n\r\n\t\t\t\t\t\tface = faces[ i ];\r\n\t\t\t\t\t\tf3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.addGroup( start, verticesArray.length / 3 - start, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Create faces for the z-sides of the shape\r\n\r\n\t\t\tfunction buildSideFaces() {\r\n\r\n\t\t\t\tvar start = verticesArray.length / 3;\r\n\t\t\t\tvar layeroffset = 0;\r\n\t\t\t\tsidewalls( contour, layeroffset );\r\n\t\t\t\tlayeroffset += contour.length;\r\n\r\n\t\t\t\tfor ( h = 0, hl = holes.length; h < hl; h ++ ) {\r\n\r\n\t\t\t\t\tahole = holes[ h ];\r\n\t\t\t\t\tsidewalls( ahole, layeroffset );\r\n\r\n\t\t\t\t\t//, true\r\n\t\t\t\t\tlayeroffset += ahole.length;\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tscope.addGroup( start, verticesArray.length / 3 - start, 1 );\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction sidewalls( contour, layeroffset ) {\r\n\r\n\t\t\t\tvar j, k;\r\n\t\t\t\ti = contour.length;\r\n\r\n\t\t\t\twhile ( -- i >= 0 ) {\r\n\r\n\t\t\t\t\tj = i;\r\n\t\t\t\t\tk = i - 1;\r\n\t\t\t\t\tif ( k < 0 ) { k = contour.length - 1; }\r\n\r\n\t\t\t\t\t//console.log('b', i,j, i-1, k,vertices.length);\r\n\r\n\t\t\t\t\tvar s = 0,\r\n\t\t\t\t\t\tsl = steps + bevelSegments * 2;\r\n\r\n\t\t\t\t\tfor ( s = 0; s < sl; s ++ ) {\r\n\r\n\t\t\t\t\t\tvar slen1 = vlen * s;\r\n\t\t\t\t\t\tvar slen2 = vlen * ( s + 1 );\r\n\r\n\t\t\t\t\t\tvar a = layeroffset + j + slen1,\r\n\t\t\t\t\t\t\tb = layeroffset + k + slen1,\r\n\t\t\t\t\t\t\tc = layeroffset + k + slen2,\r\n\t\t\t\t\t\t\td = layeroffset + j + slen2;\r\n\r\n\t\t\t\t\t\tf4( a, b, c, d );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction v( x, y, z ) {\r\n\r\n\t\t\t\tplaceholder.push( x );\r\n\t\t\t\tplaceholder.push( y );\r\n\t\t\t\tplaceholder.push( z );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction f3( a, b, c ) {\r\n\r\n\t\t\t\taddVertex( a );\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( c );\r\n\r\n\t\t\t\tvar nextIndex = verticesArray.length / 3;\r\n\t\t\t\tvar uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );\r\n\r\n\t\t\t\taddUV( uvs[ 0 ] );\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 2 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction f4( a, b, c, d ) {\r\n\r\n\t\t\t\taddVertex( a );\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( d );\r\n\r\n\t\t\t\taddVertex( b );\r\n\t\t\t\taddVertex( c );\r\n\t\t\t\taddVertex( d );\r\n\r\n\r\n\t\t\t\tvar nextIndex = verticesArray.length / 3;\r\n\t\t\t\tvar uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );\r\n\r\n\t\t\t\taddUV( uvs[ 0 ] );\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 3 ] );\r\n\r\n\t\t\t\taddUV( uvs[ 1 ] );\r\n\t\t\t\taddUV( uvs[ 2 ] );\r\n\t\t\t\taddUV( uvs[ 3 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction addVertex( index ) {\r\n\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 0 ] );\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 1 ] );\r\n\t\t\t\tverticesArray.push( placeholder[ index * 3 + 2 ] );\r\n\r\n\t\t\t}\r\n\r\n\r\n\t\t\tfunction addUV( vector2 ) {\r\n\r\n\t\t\t\tuvArray.push( vector2.x );\r\n\t\t\t\tuvArray.push( vector2.y );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry;\r\n\r\n\tExtrudeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\t\tvar options = this.parameters.options;\r\n\r\n\t\treturn toJSON( shapes, options, data );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar WorldUVGenerator = {\r\n\r\n\t\tgenerateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) {\r\n\r\n\t\t\tvar a_x = vertices[ indexA * 3 ];\r\n\t\t\tvar a_y = vertices[ indexA * 3 + 1 ];\r\n\t\t\tvar b_x = vertices[ indexB * 3 ];\r\n\t\t\tvar b_y = vertices[ indexB * 3 + 1 ];\r\n\t\t\tvar c_x = vertices[ indexC * 3 ];\r\n\t\t\tvar c_y = vertices[ indexC * 3 + 1 ];\r\n\r\n\t\t\treturn [\r\n\t\t\t\tnew Vector2( a_x, a_y ),\r\n\t\t\t\tnew Vector2( b_x, b_y ),\r\n\t\t\t\tnew Vector2( c_x, c_y )\r\n\t\t\t];\r\n\r\n\t\t},\r\n\r\n\t\tgenerateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) {\r\n\r\n\t\t\tvar a_x = vertices[ indexA * 3 ];\r\n\t\t\tvar a_y = vertices[ indexA * 3 + 1 ];\r\n\t\t\tvar a_z = vertices[ indexA * 3 + 2 ];\r\n\t\t\tvar b_x = vertices[ indexB * 3 ];\r\n\t\t\tvar b_y = vertices[ indexB * 3 + 1 ];\r\n\t\t\tvar b_z = vertices[ indexB * 3 + 2 ];\r\n\t\t\tvar c_x = vertices[ indexC * 3 ];\r\n\t\t\tvar c_y = vertices[ indexC * 3 + 1 ];\r\n\t\t\tvar c_z = vertices[ indexC * 3 + 2 ];\r\n\t\t\tvar d_x = vertices[ indexD * 3 ];\r\n\t\t\tvar d_y = vertices[ indexD * 3 + 1 ];\r\n\t\t\tvar d_z = vertices[ indexD * 3 + 2 ];\r\n\r\n\t\t\tif ( Math.abs( a_y - b_y ) < 0.01 ) {\r\n\r\n\t\t\t\treturn [\r\n\t\t\t\t\tnew Vector2( a_x, 1 - a_z ),\r\n\t\t\t\t\tnew Vector2( b_x, 1 - b_z ),\r\n\t\t\t\t\tnew Vector2( c_x, 1 - c_z ),\r\n\t\t\t\t\tnew Vector2( d_x, 1 - d_z )\r\n\t\t\t\t];\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn [\r\n\t\t\t\t\tnew Vector2( a_y, 1 - a_z ),\r\n\t\t\t\t\tnew Vector2( b_y, 1 - b_z ),\r\n\t\t\t\t\tnew Vector2( c_y, 1 - c_z ),\r\n\t\t\t\t\tnew Vector2( d_y, 1 - d_z )\r\n\t\t\t\t];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\t};\r\n\r\n\tfunction toJSON( shapes, options, data ) {\r\n\r\n\t\t//\r\n\r\n\t\tdata.shapes = [];\r\n\r\n\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\tdata.shapes.push( shape.uuid );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tdata.shapes.push( shapes.uuid );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tif ( options.extrudePath !== undefined ) { data.options.extrudePath = options.extrudePath.toJSON(); }\r\n\r\n\t\treturn data;\r\n\r\n\t}\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * Text = 3D Text\r\n\t *\r\n\t * parameters = {\r\n\t * font: , // font\r\n\t *\r\n\t * size: , // size of the text\r\n\t * height: , // thickness to extrude text\r\n\t * curveSegments: , // number of points on the curves\r\n\t *\r\n\t * bevelEnabled: , // turn on bevel\r\n\t * bevelThickness: , // how deep into text bevel goes\r\n\t * bevelSize: , // how far from text outline (including bevelOffset) is bevel\r\n\t * bevelOffset: // how far from text outline does bevel start\r\n\t * }\r\n\t */\r\n\r\n\t// TextGeometry\r\n\r\n\tfunction TextGeometry( text, parameters ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'TextGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\ttext: text,\r\n\t\t\tparameters: parameters\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new TextBufferGeometry( text, parameters ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tTextGeometry.prototype = Object.create( Geometry.prototype );\r\n\tTextGeometry.prototype.constructor = TextGeometry;\r\n\r\n\t// TextBufferGeometry\r\n\r\n\tfunction TextBufferGeometry( text, parameters ) {\r\n\r\n\t\tparameters = parameters || {};\r\n\r\n\t\tvar font = parameters.font;\r\n\r\n\t\tif ( ! ( font && font.isFont ) ) {\r\n\r\n\t\t\tconsole.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' );\r\n\t\t\treturn new Geometry();\r\n\r\n\t\t}\r\n\r\n\t\tvar shapes = font.generateShapes( text, parameters.size );\r\n\r\n\t\t// translate parameters to ExtrudeGeometry API\r\n\r\n\t\tparameters.depth = parameters.height !== undefined ? parameters.height : 50;\r\n\r\n\t\t// defaults\r\n\r\n\t\tif ( parameters.bevelThickness === undefined ) { parameters.bevelThickness = 10; }\r\n\t\tif ( parameters.bevelSize === undefined ) { parameters.bevelSize = 8; }\r\n\t\tif ( parameters.bevelEnabled === undefined ) { parameters.bevelEnabled = false; }\r\n\r\n\t\tExtrudeBufferGeometry.call( this, shapes, parameters );\r\n\r\n\t\tthis.type = 'TextBufferGeometry';\r\n\r\n\t}\r\n\r\n\tTextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype );\r\n\tTextBufferGeometry.prototype.constructor = TextBufferGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// SphereGeometry\r\n\r\n\tfunction SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'SphereGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tSphereGeometry.prototype = Object.create( Geometry.prototype );\r\n\tSphereGeometry.prototype.constructor = SphereGeometry;\r\n\r\n\t// SphereBufferGeometry\r\n\r\n\tfunction SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'SphereBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\twidthSegments: widthSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\r\n\t\twidthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 );\r\n\t\theightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 );\r\n\r\n\t\tphiStart = phiStart !== undefined ? phiStart : 0;\r\n\t\tphiLength = phiLength !== undefined ? phiLength : Math.PI * 2;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI;\r\n\r\n\t\tvar thetaEnd = Math.min( thetaStart + thetaLength, Math.PI );\r\n\r\n\t\tvar ix, iy;\r\n\r\n\t\tvar index = 0;\r\n\t\tvar grid = [];\r\n\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar normal = new Vector3();\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( iy = 0; iy <= heightSegments; iy ++ ) {\r\n\r\n\t\t\tvar verticesRow = [];\r\n\r\n\t\t\tvar v = iy / heightSegments;\r\n\r\n\t\t\t// special case for the poles\r\n\r\n\t\t\tvar uOffset = 0;\r\n\r\n\t\t\tif ( iy == 0 && thetaStart == 0 ) {\r\n\r\n\t\t\t\tuOffset = 0.5 / widthSegments;\r\n\r\n\t\t\t} else if ( iy == heightSegments && thetaEnd == Math.PI ) {\r\n\r\n\t\t\t\tuOffset = - 0.5 / widthSegments;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( ix = 0; ix <= widthSegments; ix ++ ) {\r\n\r\n\t\t\t\tvar u = ix / widthSegments;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );\r\n\t\t\t\tvertex.y = radius * Math.cos( thetaStart + v * thetaLength );\r\n\t\t\t\tvertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormal.copy( vertex ).normalize();\r\n\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( u + uOffset, 1 - v );\r\n\r\n\t\t\t\tverticesRow.push( index ++ );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgrid.push( verticesRow );\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( iy = 0; iy < heightSegments; iy ++ ) {\r\n\r\n\t\t\tfor ( ix = 0; ix < widthSegments; ix ++ ) {\r\n\r\n\t\t\t\tvar a = grid[ iy ][ ix + 1 ];\r\n\t\t\t\tvar b = grid[ iy ][ ix ];\r\n\t\t\t\tvar c = grid[ iy + 1 ][ ix ];\r\n\t\t\t\tvar d = grid[ iy + 1 ][ ix + 1 ];\r\n\r\n\t\t\t\tif ( iy !== 0 || thetaStart > 0 ) { indices.push( a, b, d ); }\r\n\t\t\t\tif ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) { indices.push( b, c, d ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tSphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tSphereBufferGeometry.prototype.constructor = SphereBufferGeometry;\n\n\t/**\r\n\t * @author Kaleb Murphy\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// RingGeometry\r\n\r\n\tfunction RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'RingGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tinnerRadius: innerRadius,\r\n\t\t\touterRadius: outerRadius,\r\n\t\t\tthetaSegments: thetaSegments,\r\n\t\t\tphiSegments: phiSegments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tRingGeometry.prototype = Object.create( Geometry.prototype );\r\n\tRingGeometry.prototype.constructor = RingGeometry;\r\n\r\n\t// RingBufferGeometry\r\n\r\n\tfunction RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'RingBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tinnerRadius: innerRadius,\r\n\t\t\touterRadius: outerRadius,\r\n\t\t\tthetaSegments: thetaSegments,\r\n\t\t\tphiSegments: phiSegments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tinnerRadius = innerRadius || 0.5;\r\n\t\touterRadius = outerRadius || 1;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\tthetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8;\r\n\t\tphiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// some helper variables\r\n\r\n\t\tvar segment;\r\n\t\tvar radius = innerRadius;\r\n\t\tvar radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar j, i;\r\n\r\n\t\t// generate vertices, normals and uvs\r\n\r\n\t\tfor ( j = 0; j <= phiSegments; j ++ ) {\r\n\r\n\t\t\tfor ( i = 0; i <= thetaSegments; i ++ ) {\r\n\r\n\t\t\t\t// values are generate from the inside of the ring to the outside\r\n\r\n\t\t\t\tsegment = thetaStart + i / thetaSegments * thetaLength;\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = radius * Math.cos( segment );\r\n\t\t\t\tvertex.y = radius * Math.sin( segment );\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = ( vertex.x / outerRadius + 1 ) / 2;\r\n\t\t\t\tuv.y = ( vertex.y / outerRadius + 1 ) / 2;\r\n\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// increase the radius for next row of vertices\r\n\r\n\t\t\tradius += radiusStep;\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( j = 0; j < phiSegments; j ++ ) {\r\n\r\n\t\t\tvar thetaSegmentLevel = j * ( thetaSegments + 1 );\r\n\r\n\t\t\tfor ( i = 0; i < thetaSegments; i ++ ) {\r\n\r\n\t\t\t\tsegment = i + thetaSegmentLevel;\r\n\r\n\t\t\t\tvar a = segment;\r\n\t\t\t\tvar b = segment + thetaSegments + 1;\r\n\t\t\t\tvar c = segment + thetaSegments + 2;\r\n\t\t\t\tvar d = segment + 1;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tRingBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tRingBufferGeometry.prototype.constructor = RingBufferGeometry;\n\n\t/**\r\n\t * @author zz85 / https://github.com/zz85\r\n\t * @author bhouston / http://clara.io\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// LatheGeometry\r\n\r\n\tfunction LatheGeometry( points, segments, phiStart, phiLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'LatheGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpoints: points,\r\n\t\t\tsegments: segments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tLatheGeometry.prototype = Object.create( Geometry.prototype );\r\n\tLatheGeometry.prototype.constructor = LatheGeometry;\r\n\r\n\t// LatheBufferGeometry\r\n\r\n\tfunction LatheBufferGeometry( points, segments, phiStart, phiLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'LatheBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tpoints: points,\r\n\t\t\tsegments: segments,\r\n\t\t\tphiStart: phiStart,\r\n\t\t\tphiLength: phiLength\r\n\t\t};\r\n\r\n\t\tsegments = Math.floor( segments ) || 12;\r\n\t\tphiStart = phiStart || 0;\r\n\t\tphiLength = phiLength || Math.PI * 2;\r\n\r\n\t\t// clamp phiLength so it's in range of [ 0, 2PI ]\r\n\r\n\t\tphiLength = _Math.clamp( phiLength, 0, Math.PI * 2 );\r\n\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar base;\r\n\t\tvar inverseSegments = 1.0 / segments;\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\t\tvar i, j;\r\n\r\n\t\t// generate vertices and uvs\r\n\r\n\t\tfor ( i = 0; i <= segments; i ++ ) {\r\n\r\n\t\t\tvar phi = phiStart + i * inverseSegments * phiLength;\r\n\r\n\t\t\tvar sin = Math.sin( phi );\r\n\t\t\tvar cos = Math.cos( phi );\r\n\r\n\t\t\tfor ( j = 0; j <= ( points.length - 1 ); j ++ ) {\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = points[ j ].x * sin;\r\n\t\t\t\tvertex.y = points[ j ].y;\r\n\t\t\t\tvertex.z = points[ j ].x * cos;\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = i / segments;\r\n\t\t\t\tuv.y = j / ( points.length - 1 );\r\n\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( i = 0; i < segments; i ++ ) {\r\n\r\n\t\t\tfor ( j = 0; j < ( points.length - 1 ); j ++ ) {\r\n\r\n\t\t\t\tbase = j + i * points.length;\r\n\r\n\t\t\t\tvar a = base;\r\n\t\t\t\tvar b = base + points.length;\r\n\t\t\t\tvar c = base + points.length + 1;\r\n\t\t\t\tvar d = base + 1;\r\n\r\n\t\t\t\t// faces\r\n\r\n\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\t// generate normals\r\n\r\n\t\tthis.computeVertexNormals();\r\n\r\n\t\t// if the geometry is closed, we need to average the normals along the seam.\r\n\t\t// because the corresponding vertices are identical (but still have different UVs).\r\n\r\n\t\tif ( phiLength === Math.PI * 2 ) {\r\n\r\n\t\t\tvar normals = this.attributes.normal.array;\r\n\t\t\tvar n1 = new Vector3();\r\n\t\t\tvar n2 = new Vector3();\r\n\t\t\tvar n = new Vector3();\r\n\r\n\t\t\t// this is the buffer offset for the last line of vertices\r\n\r\n\t\t\tbase = segments * points.length * 3;\r\n\r\n\t\t\tfor ( i = 0, j = 0; i < points.length; i ++, j += 3 ) {\r\n\r\n\t\t\t\t// select the normal of the vertex in the first line\r\n\r\n\t\t\t\tn1.x = normals[ j + 0 ];\r\n\t\t\t\tn1.y = normals[ j + 1 ];\r\n\t\t\t\tn1.z = normals[ j + 2 ];\r\n\r\n\t\t\t\t// select the normal of the vertex in the last line\r\n\r\n\t\t\t\tn2.x = normals[ base + j + 0 ];\r\n\t\t\t\tn2.y = normals[ base + j + 1 ];\r\n\t\t\t\tn2.z = normals[ base + j + 2 ];\r\n\r\n\t\t\t\t// average normals\r\n\r\n\t\t\t\tn.addVectors( n1, n2 ).normalize();\r\n\r\n\t\t\t\t// assign the new values to both normals\r\n\r\n\t\t\t\tnormals[ j + 0 ] = normals[ base + j + 0 ] = n.x;\r\n\t\t\t\tnormals[ j + 1 ] = normals[ base + j + 1 ] = n.y;\r\n\t\t\t\tnormals[ j + 2 ] = normals[ base + j + 2 ] = n.z;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tLatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tLatheBufferGeometry.prototype.constructor = LatheBufferGeometry;\n\n\t/**\r\n\t * @author jonobr1 / http://jonobr1.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// ShapeGeometry\r\n\r\n\tfunction ShapeGeometry( shapes, curveSegments ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'ShapeGeometry';\r\n\r\n\t\tif ( typeof curveSegments === 'object' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' );\r\n\r\n\t\t\tcurveSegments = curveSegments.curveSegments;\r\n\r\n\t\t}\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\tcurveSegments: curveSegments\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tShapeGeometry.prototype = Object.create( Geometry.prototype );\r\n\tShapeGeometry.prototype.constructor = ShapeGeometry;\r\n\r\n\tShapeGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Geometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\r\n\t\treturn toJSON$1( shapes, data );\r\n\r\n\t};\r\n\r\n\t// ShapeBufferGeometry\r\n\r\n\tfunction ShapeBufferGeometry( shapes, curveSegments ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'ShapeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tshapes: shapes,\r\n\t\t\tcurveSegments: curveSegments\r\n\t\t};\r\n\r\n\t\tcurveSegments = curveSegments || 12;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar groupStart = 0;\r\n\t\tvar groupCount = 0;\r\n\r\n\t\t// allow single and array values for \"shapes\" parameter\r\n\r\n\t\tif ( Array.isArray( shapes ) === false ) {\r\n\r\n\t\t\taddShape( shapes );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tfor ( var i = 0; i < shapes.length; i ++ ) {\r\n\r\n\t\t\t\taddShape( shapes[ i ] );\r\n\r\n\t\t\t\tthis.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support\r\n\r\n\t\t\t\tgroupStart += groupCount;\r\n\t\t\t\tgroupCount = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\r\n\t\t// helper functions\r\n\r\n\t\tfunction addShape( shape ) {\r\n\r\n\t\t\tvar i, l, shapeHole;\r\n\r\n\t\t\tvar indexOffset = vertices.length / 3;\r\n\t\t\tvar points = shape.extractPoints( curveSegments );\r\n\r\n\t\t\tvar shapeVertices = points.shape;\r\n\t\t\tvar shapeHoles = points.holes;\r\n\r\n\t\t\t// check direction of vertices\r\n\r\n\t\t\tif ( ShapeUtils.isClockWise( shapeVertices ) === false ) {\r\n\r\n\t\t\t\tshapeVertices = shapeVertices.reverse();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( i = 0, l = shapeHoles.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tshapeHole = shapeHoles[ i ];\r\n\r\n\t\t\t\tif ( ShapeUtils.isClockWise( shapeHole ) === true ) {\r\n\r\n\t\t\t\t\tshapeHoles[ i ] = shapeHole.reverse();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );\r\n\r\n\t\t\t// join vertices of inner and outer paths to a single array\r\n\r\n\t\t\tfor ( i = 0, l = shapeHoles.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tshapeHole = shapeHoles[ i ];\r\n\t\t\t\tshapeVertices = shapeVertices.concat( shapeHole );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// vertices, normals, uvs\r\n\r\n\t\t\tfor ( i = 0, l = shapeVertices.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar vertex = shapeVertices[ i ];\r\n\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, 0 );\r\n\t\t\t\tnormals.push( 0, 0, 1 );\r\n\t\t\t\tuvs.push( vertex.x, vertex.y ); // world uvs\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// incides\r\n\r\n\t\t\tfor ( i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tvar a = face[ 0 ] + indexOffset;\r\n\t\t\t\tvar b = face[ 1 ] + indexOffset;\r\n\t\t\t\tvar c = face[ 2 ] + indexOffset;\r\n\r\n\t\t\t\tindices.push( a, b, c );\r\n\t\t\t\tgroupCount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry;\r\n\r\n\tShapeBufferGeometry.prototype.toJSON = function () {\r\n\r\n\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\tvar shapes = this.parameters.shapes;\r\n\r\n\t\treturn toJSON$1( shapes, data );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction toJSON$1( shapes, data ) {\r\n\r\n\t\tdata.shapes = [];\r\n\r\n\t\tif ( Array.isArray( shapes ) ) {\r\n\r\n\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar shape = shapes[ i ];\r\n\r\n\t\t\t\tdata.shapes.push( shape.uuid );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\tdata.shapes.push( shapes.uuid );\r\n\r\n\t\t}\r\n\r\n\t\treturn data;\r\n\r\n\t}\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction EdgesGeometry( geometry, thresholdAngle ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'EdgesGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tthresholdAngle: thresholdAngle\r\n\t\t};\r\n\r\n\t\tthresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;\r\n\r\n\t\t// buffer\r\n\r\n\t\tvar vertices = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle );\r\n\t\tvar edge = [ 0, 0 ], edges = {}, edge1, edge2;\r\n\t\tvar key, keys = [ 'a', 'b', 'c' ];\r\n\r\n\t\t// prepare source geometry\r\n\r\n\t\tvar geometry2;\r\n\r\n\t\tif ( geometry.isBufferGeometry ) {\r\n\r\n\t\t\tgeometry2 = new Geometry();\r\n\t\t\tgeometry2.fromBufferGeometry( geometry );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tgeometry2 = geometry.clone();\r\n\r\n\t\t}\r\n\r\n\t\tgeometry2.mergeVertices();\r\n\t\tgeometry2.computeFaceNormals();\r\n\r\n\t\tvar sourceVertices = geometry2.vertices;\r\n\t\tvar faces = geometry2.faces;\r\n\r\n\t\t// now create a data structure where each entry represents an edge with its adjoining faces\r\n\r\n\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\tfor ( var j = 0; j < 3; j ++ ) {\r\n\r\n\t\t\t\tedge1 = face[ keys[ j ] ];\r\n\t\t\t\tedge2 = face[ keys[ ( j + 1 ) % 3 ] ];\r\n\t\t\t\tedge[ 0 ] = Math.min( edge1, edge2 );\r\n\t\t\t\tedge[ 1 ] = Math.max( edge1, edge2 );\r\n\r\n\t\t\t\tkey = edge[ 0 ] + ',' + edge[ 1 ];\r\n\r\n\t\t\t\tif ( edges[ key ] === undefined ) {\r\n\r\n\t\t\t\t\tedges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined };\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tedges[ key ].face2 = i;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// generate vertices\r\n\r\n\t\tfor ( key in edges ) {\r\n\r\n\t\t\tvar e = edges[ key ];\r\n\r\n\t\t\t// an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree.\r\n\r\n\t\t\tif ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) {\r\n\r\n\t\t\t\tvar vertex = sourceVertices[ e.index1 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\tvertex = sourceVertices[ e.index2 ];\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\r\n\t}\r\n\r\n\tEdgesGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tEdgesGeometry.prototype.constructor = EdgesGeometry;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\t// CylinderGeometry\r\n\r\n\tfunction CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'CylinderGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradiusTop: radiusTop,\r\n\t\t\tradiusBottom: radiusBottom,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tCylinderGeometry.prototype = Object.create( Geometry.prototype );\r\n\tCylinderGeometry.prototype.constructor = CylinderGeometry;\r\n\r\n\t// CylinderBufferGeometry\r\n\r\n\tfunction CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'CylinderBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradiusTop: radiusTop,\r\n\t\t\tradiusBottom: radiusBottom,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tradiusTop = radiusTop !== undefined ? radiusTop : 1;\r\n\t\tradiusBottom = radiusBottom !== undefined ? radiusBottom : 1;\r\n\t\theight = height || 1;\r\n\r\n\t\tradialSegments = Math.floor( radialSegments ) || 8;\r\n\t\theightSegments = Math.floor( heightSegments ) || 1;\r\n\r\n\t\topenEnded = openEnded !== undefined ? openEnded : false;\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0.0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar index = 0;\r\n\t\tvar indexArray = [];\r\n\t\tvar halfHeight = height / 2;\r\n\t\tvar groupStart = 0;\r\n\r\n\t\t// generate geometry\r\n\r\n\t\tgenerateTorso();\r\n\r\n\t\tif ( openEnded === false ) {\r\n\r\n\t\t\tif ( radiusTop > 0 ) { generateCap( true ); }\r\n\t\t\tif ( radiusBottom > 0 ) { generateCap( false ); }\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t\tfunction generateTorso() {\r\n\r\n\t\t\tvar x, y;\r\n\t\t\tvar normal = new Vector3();\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tvar groupCount = 0;\r\n\r\n\t\t\t// this will be used to calculate the normal\r\n\t\t\tvar slope = ( radiusBottom - radiusTop ) / height;\r\n\r\n\t\t\t// generate vertices, normals and uvs\r\n\r\n\t\t\tfor ( y = 0; y <= heightSegments; y ++ ) {\r\n\r\n\t\t\t\tvar indexRow = [];\r\n\r\n\t\t\t\tvar v = y / heightSegments;\r\n\r\n\t\t\t\t// calculate the radius of the current row\r\n\r\n\t\t\t\tvar radius = v * ( radiusBottom - radiusTop ) + radiusTop;\r\n\r\n\t\t\t\tfor ( x = 0; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\t\tvar u = x / radialSegments;\r\n\r\n\t\t\t\t\tvar theta = u * thetaLength + thetaStart;\r\n\r\n\t\t\t\t\tvar sinTheta = Math.sin( theta );\r\n\t\t\t\t\tvar cosTheta = Math.cos( theta );\r\n\r\n\t\t\t\t\t// vertex\r\n\r\n\t\t\t\t\tvertex.x = radius * sinTheta;\r\n\t\t\t\t\tvertex.y = - v * height + halfHeight;\r\n\t\t\t\t\tvertex.z = radius * cosTheta;\r\n\t\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t\t// normal\r\n\r\n\t\t\t\t\tnormal.set( sinTheta, slope, cosTheta ).normalize();\r\n\t\t\t\t\tnormals.push( normal.x, normal.y, normal.z );\r\n\r\n\t\t\t\t\t// uv\r\n\r\n\t\t\t\t\tuvs.push( u, 1 - v );\r\n\r\n\t\t\t\t\t// save index of vertex in respective row\r\n\r\n\t\t\t\t\tindexRow.push( index ++ );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// now save vertices of the row in our index array\r\n\r\n\t\t\t\tindexArray.push( indexRow );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate indices\r\n\r\n\t\t\tfor ( x = 0; x < radialSegments; x ++ ) {\r\n\r\n\t\t\t\tfor ( y = 0; y < heightSegments; y ++ ) {\r\n\r\n\t\t\t\t\t// we use the index array to access the correct indices\r\n\r\n\t\t\t\t\tvar a = indexArray[ y ][ x ];\r\n\t\t\t\t\tvar b = indexArray[ y + 1 ][ x ];\r\n\t\t\t\t\tvar c = indexArray[ y + 1 ][ x + 1 ];\r\n\t\t\t\t\tvar d = indexArray[ y ][ x + 1 ];\r\n\r\n\t\t\t\t\t// faces\r\n\r\n\t\t\t\t\tindices.push( a, b, d );\r\n\t\t\t\t\tindices.push( b, c, d );\r\n\r\n\t\t\t\t\t// update group counter\r\n\r\n\t\t\t\t\tgroupCount += 6;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\tscope.addGroup( groupStart, groupCount, 0 );\r\n\r\n\t\t\t// calculate new start value for groups\r\n\r\n\t\t\tgroupStart += groupCount;\r\n\r\n\t\t}\r\n\r\n\t\tfunction generateCap( top ) {\r\n\r\n\t\t\tvar x, centerIndexStart, centerIndexEnd;\r\n\r\n\t\t\tvar uv = new Vector2();\r\n\t\t\tvar vertex = new Vector3();\r\n\r\n\t\t\tvar groupCount = 0;\r\n\r\n\t\t\tvar radius = ( top === true ) ? radiusTop : radiusBottom;\r\n\t\t\tvar sign = ( top === true ) ? 1 : - 1;\r\n\r\n\t\t\t// save the index of the first center vertex\r\n\t\t\tcenterIndexStart = index;\r\n\r\n\t\t\t// first we generate the center vertex data of the cap.\r\n\t\t\t// because the geometry needs one set of uvs per face,\r\n\t\t\t// we must generate a center vertex per face/segment\r\n\r\n\t\t\tfor ( x = 1; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertices.push( 0, halfHeight * sign, 0 );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, sign, 0 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuvs.push( 0.5, 0.5 );\r\n\r\n\t\t\t\t// increase index\r\n\r\n\t\t\t\tindex ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// save the index of the last center vertex\r\n\r\n\t\t\tcenterIndexEnd = index;\r\n\r\n\t\t\t// now we generate the surrounding vertices, normals and uvs\r\n\r\n\t\t\tfor ( x = 0; x <= radialSegments; x ++ ) {\r\n\r\n\t\t\t\tvar u = x / radialSegments;\r\n\t\t\t\tvar theta = u * thetaLength + thetaStart;\r\n\r\n\t\t\t\tvar cosTheta = Math.cos( theta );\r\n\t\t\t\tvar sinTheta = Math.sin( theta );\r\n\r\n\t\t\t\t// vertex\r\n\r\n\t\t\t\tvertex.x = radius * sinTheta;\r\n\t\t\t\tvertex.y = halfHeight * sign;\r\n\t\t\t\tvertex.z = radius * cosTheta;\r\n\t\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t\t// normal\r\n\r\n\t\t\t\tnormals.push( 0, sign, 0 );\r\n\r\n\t\t\t\t// uv\r\n\r\n\t\t\t\tuv.x = ( cosTheta * 0.5 ) + 0.5;\r\n\t\t\t\tuv.y = ( sinTheta * 0.5 * sign ) + 0.5;\r\n\t\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t\t\t// increase index\r\n\r\n\t\t\t\tindex ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// generate indices\r\n\r\n\t\t\tfor ( x = 0; x < radialSegments; x ++ ) {\r\n\r\n\t\t\t\tvar c = centerIndexStart + x;\r\n\t\t\t\tvar i = centerIndexEnd + x;\r\n\r\n\t\t\t\tif ( top === true ) {\r\n\r\n\t\t\t\t\t// face top\r\n\r\n\t\t\t\t\tindices.push( i, i + 1, c );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// face bottom\r\n\r\n\t\t\t\t\tindices.push( i + 1, i, c );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgroupCount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// add a group to the geometry. this will ensure multi material support\r\n\r\n\t\t\tscope.addGroup( groupStart, groupCount, top === true ? 1 : 2 );\r\n\r\n\t\t\t// calculate new start value for groups\r\n\r\n\t\t\tgroupStart += groupCount;\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tCylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tCylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry;\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t */\r\n\r\n\t// ConeGeometry\r\n\r\n\tfunction ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tCylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );\r\n\r\n\t\tthis.type = 'ConeGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tConeGeometry.prototype = Object.create( CylinderGeometry.prototype );\r\n\tConeGeometry.prototype.constructor = ConeGeometry;\r\n\r\n\t// ConeBufferGeometry\r\n\r\n\tfunction ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) {\r\n\r\n\t\tCylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );\r\n\r\n\t\tthis.type = 'ConeBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\theight: height,\r\n\t\t\tradialSegments: radialSegments,\r\n\t\t\theightSegments: heightSegments,\r\n\t\t\topenEnded: openEnded,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype );\r\n\tConeBufferGeometry.prototype.constructor = ConeBufferGeometry;\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t * @author hughes\r\n\t */\r\n\r\n\t// CircleGeometry\r\n\r\n\tfunction CircleGeometry( radius, segments, thetaStart, thetaLength ) {\r\n\r\n\t\tGeometry.call( this );\r\n\r\n\t\tthis.type = 'CircleGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tsegments: segments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tthis.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) );\r\n\t\tthis.mergeVertices();\r\n\r\n\t}\r\n\r\n\tCircleGeometry.prototype = Object.create( Geometry.prototype );\r\n\tCircleGeometry.prototype.constructor = CircleGeometry;\r\n\r\n\t// CircleBufferGeometry\r\n\r\n\tfunction CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'CircleBufferGeometry';\r\n\r\n\t\tthis.parameters = {\r\n\t\t\tradius: radius,\r\n\t\t\tsegments: segments,\r\n\t\t\tthetaStart: thetaStart,\r\n\t\t\tthetaLength: thetaLength\r\n\t\t};\r\n\r\n\t\tradius = radius || 1;\r\n\t\tsegments = segments !== undefined ? Math.max( 3, segments ) : 8;\r\n\r\n\t\tthetaStart = thetaStart !== undefined ? thetaStart : 0;\r\n\t\tthetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;\r\n\r\n\t\t// buffers\r\n\r\n\t\tvar indices = [];\r\n\t\tvar vertices = [];\r\n\t\tvar normals = [];\r\n\t\tvar uvs = [];\r\n\r\n\t\t// helper variables\r\n\r\n\t\tvar i, s;\r\n\t\tvar vertex = new Vector3();\r\n\t\tvar uv = new Vector2();\r\n\r\n\t\t// center point\r\n\r\n\t\tvertices.push( 0, 0, 0 );\r\n\t\tnormals.push( 0, 0, 1 );\r\n\t\tuvs.push( 0.5, 0.5 );\r\n\r\n\t\tfor ( s = 0, i = 3; s <= segments; s ++, i += 3 ) {\r\n\r\n\t\t\tvar segment = thetaStart + s / segments * thetaLength;\r\n\r\n\t\t\t// vertex\r\n\r\n\t\t\tvertex.x = radius * Math.cos( segment );\r\n\t\t\tvertex.y = radius * Math.sin( segment );\r\n\r\n\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\r\n\r\n\t\t\t// normal\r\n\r\n\t\t\tnormals.push( 0, 0, 1 );\r\n\r\n\t\t\t// uvs\r\n\r\n\t\t\tuv.x = ( vertices[ i ] / radius + 1 ) / 2;\r\n\t\t\tuv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2;\r\n\r\n\t\t\tuvs.push( uv.x, uv.y );\r\n\r\n\t\t}\r\n\r\n\t\t// indices\r\n\r\n\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\tindices.push( i, i + 1, 0 );\r\n\r\n\t\t}\r\n\r\n\t\t// build geometry\r\n\r\n\t\tthis.setIndex( indices );\r\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\r\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\r\n\r\n\t}\r\n\r\n\tCircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\r\n\tCircleBufferGeometry.prototype.constructor = CircleBufferGeometry;\n\n\n\n\tvar Geometries = /*#__PURE__*/Object.freeze({\n\t\t__proto__: null,\n\t\tWireframeGeometry: WireframeGeometry,\n\t\tParametricGeometry: ParametricGeometry,\n\t\tParametricBufferGeometry: ParametricBufferGeometry,\n\t\tTetrahedronGeometry: TetrahedronGeometry,\n\t\tTetrahedronBufferGeometry: TetrahedronBufferGeometry,\n\t\tOctahedronGeometry: OctahedronGeometry,\n\t\tOctahedronBufferGeometry: OctahedronBufferGeometry,\n\t\tIcosahedronGeometry: IcosahedronGeometry,\n\t\tIcosahedronBufferGeometry: IcosahedronBufferGeometry,\n\t\tDodecahedronGeometry: DodecahedronGeometry,\n\t\tDodecahedronBufferGeometry: DodecahedronBufferGeometry,\n\t\tPolyhedronGeometry: PolyhedronGeometry,\n\t\tPolyhedronBufferGeometry: PolyhedronBufferGeometry,\n\t\tTubeGeometry: TubeGeometry,\n\t\tTubeBufferGeometry: TubeBufferGeometry,\n\t\tTorusKnotGeometry: TorusKnotGeometry,\n\t\tTorusKnotBufferGeometry: TorusKnotBufferGeometry,\n\t\tTorusGeometry: TorusGeometry,\n\t\tTorusBufferGeometry: TorusBufferGeometry,\n\t\tTextGeometry: TextGeometry,\n\t\tTextBufferGeometry: TextBufferGeometry,\n\t\tSphereGeometry: SphereGeometry,\n\t\tSphereBufferGeometry: SphereBufferGeometry,\n\t\tRingGeometry: RingGeometry,\n\t\tRingBufferGeometry: RingBufferGeometry,\n\t\tPlaneGeometry: PlaneGeometry,\n\t\tPlaneBufferGeometry: PlaneBufferGeometry,\n\t\tLatheGeometry: LatheGeometry,\n\t\tLatheBufferGeometry: LatheBufferGeometry,\n\t\tShapeGeometry: ShapeGeometry,\n\t\tShapeBufferGeometry: ShapeBufferGeometry,\n\t\tExtrudeGeometry: ExtrudeGeometry,\n\t\tExtrudeBufferGeometry: ExtrudeBufferGeometry,\n\t\tEdgesGeometry: EdgesGeometry,\n\t\tConeGeometry: ConeGeometry,\n\t\tConeBufferGeometry: ConeBufferGeometry,\n\t\tCylinderGeometry: CylinderGeometry,\n\t\tCylinderBufferGeometry: CylinderBufferGeometry,\n\t\tCircleGeometry: CircleGeometry,\n\t\tCircleBufferGeometry: CircleBufferGeometry,\n\t\tBoxGeometry: BoxGeometry,\n\t\tBoxBufferGeometry: BoxBufferGeometry\n\t});\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: \r\n\t * }\r\n\t */\r\n\r\n\tfunction ShadowMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'ShadowMaterial';\r\n\r\n\t\tthis.color = new Color( 0x000000 );\r\n\t\tthis.transparent = true;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tShadowMaterial.prototype = Object.create( Material.prototype );\r\n\tShadowMaterial.prototype.constructor = ShadowMaterial;\r\n\r\n\tShadowMaterial.prototype.isShadowMaterial = true;\r\n\r\n\tShadowMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction RawShaderMaterial( parameters ) {\r\n\r\n\t\tShaderMaterial.call( this, parameters );\r\n\r\n\t\tthis.type = 'RawShaderMaterial';\r\n\r\n\t}\r\n\r\n\tRawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype );\r\n\tRawShaderMaterial.prototype.constructor = RawShaderMaterial;\r\n\r\n\tRawShaderMaterial.prototype.isRawShaderMaterial = true;\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * roughness: ,\r\n\t * metalness: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * roughnessMap: new THREE.Texture( ),\r\n\t *\r\n\t * metalnessMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * envMapIntensity: \r\n\t *\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshStandardMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'STANDARD': '' };\r\n\r\n\t\tthis.type = 'MeshStandardMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\t\tthis.roughness = 0.5;\r\n\t\tthis.metalness = 0.5;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.roughnessMap = null;\r\n\r\n\t\tthis.metalnessMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.envMapIntensity = 1.0;\r\n\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshStandardMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshStandardMaterial.prototype.constructor = MeshStandardMaterial;\r\n\r\n\tMeshStandardMaterial.prototype.isMeshStandardMaterial = true;\r\n\r\n\tMeshStandardMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = { 'STANDARD': '' };\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.roughness = source.roughness;\r\n\t\tthis.metalness = source.metalness;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.roughnessMap = source.roughnessMap;\r\n\r\n\t\tthis.metalnessMap = source.metalnessMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.envMapIntensity = source.envMapIntensity;\r\n\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * reflectivity: \r\n\t * clearcoat: \r\n\t * clearcoatRoughness: \r\n\t *\r\n\t * sheen: \r\n\t *\r\n\t * clearcoatNormalScale: ,\r\n\t * clearcoatNormalMap: new THREE.Texture( ),\r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshPhysicalMaterial( parameters ) {\r\n\r\n\t\tMeshStandardMaterial.call( this );\r\n\r\n\t\tthis.defines = {\r\n\r\n\t\t\t'STANDARD': '',\r\n\t\t\t'PHYSICAL': ''\r\n\r\n\t\t};\r\n\r\n\t\tthis.type = 'MeshPhysicalMaterial';\r\n\r\n\t\tthis.reflectivity = 0.5; // maps to F0 = 0.04\r\n\r\n\t\tthis.clearcoat = 0.0;\r\n\t\tthis.clearcoatRoughness = 0.0;\r\n\r\n\t\tthis.sheen = null; // null will disable sheen bsdf\r\n\r\n\t\tthis.clearcoatNormalScale = new Vector2( 1, 1 );\r\n\t\tthis.clearcoatNormalMap = null;\r\n\r\n\t\tthis.transparency = 0.0;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype );\r\n\tMeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial;\r\n\r\n\tMeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true;\r\n\r\n\tMeshPhysicalMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMeshStandardMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = {\r\n\r\n\t\t\t'STANDARD': '',\r\n\t\t\t'PHYSICAL': ''\r\n\r\n\t\t};\r\n\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\r\n\t\tthis.clearcoat = source.clearcoat;\r\n\t\tthis.clearcoatRoughness = source.clearcoatRoughness;\r\n\r\n\t\tif ( source.sheen ) { this.sheen = ( this.sheen || new Color() ).copy( source.sheen ); }\r\n\t\telse { this.sheen = null; }\r\n\r\n\t\tthis.clearcoatNormalMap = source.clearcoatNormalMap;\r\n\t\tthis.clearcoatNormalScale.copy( source.clearcoatNormalScale );\r\n\r\n\t\tthis.transparency = source.transparency;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * specular: ,\r\n\t * shininess: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.MultiplyOperation,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshPhongMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshPhongMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\t\tthis.specular = new Color( 0x111111 );\r\n\t\tthis.shininess = 30;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshPhongMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshPhongMaterial.prototype.constructor = MeshPhongMaterial;\r\n\r\n\tMeshPhongMaterial.prototype.isMeshPhongMaterial = true;\r\n\r\n\tMeshPhongMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.specular.copy( source.specular );\r\n\t\tthis.shininess = source.shininess;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author takahirox / http://github.com/takahirox\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * specular: ,\r\n\t * shininess: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t * gradientMap: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshToonMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'TOON': '' };\r\n\r\n\t\tthis.type = 'MeshToonMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff );\r\n\t\tthis.specular = new Color( 0x111111 );\r\n\t\tthis.shininess = 30;\r\n\r\n\t\tthis.map = null;\r\n\t\tthis.gradientMap = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshToonMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshToonMaterial.prototype.constructor = MeshToonMaterial;\r\n\r\n\tMeshToonMaterial.prototype.isMeshToonMaterial = true;\r\n\r\n\tMeshToonMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\t\tthis.specular.copy( source.specular );\r\n\t\tthis.shininess = source.shininess;\r\n\r\n\t\tthis.map = source.map;\r\n\t\tthis.gradientMap = source.gradientMap;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * opacity: ,\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: \r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshNormalMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshNormalMaterial';\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\r\n\t\tthis.fog = false;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshNormalMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshNormalMaterial.prototype.constructor = MeshNormalMaterial;\r\n\r\n\tMeshNormalMaterial.prototype.isMeshNormalMaterial = true;\r\n\r\n\tMeshNormalMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * lightMap: new THREE.Texture( ),\r\n\t * lightMapIntensity: \r\n\t *\r\n\t * aoMap: new THREE.Texture( ),\r\n\t * aoMapIntensity: \r\n\t *\r\n\t * emissive: ,\r\n\t * emissiveIntensity: \r\n\t * emissiveMap: new THREE.Texture( ),\r\n\t *\r\n\t * specularMap: new THREE.Texture( ),\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\r\n\t * combine: THREE.Multiply,\r\n\t * reflectivity: ,\r\n\t * refractionRatio: ,\r\n\t *\r\n\t * wireframe: ,\r\n\t * wireframeLinewidth: ,\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshLambertMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.type = 'MeshLambertMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.lightMap = null;\r\n\t\tthis.lightMapIntensity = 1.0;\r\n\r\n\t\tthis.aoMap = null;\r\n\t\tthis.aoMapIntensity = 1.0;\r\n\r\n\t\tthis.emissive = new Color( 0x000000 );\r\n\t\tthis.emissiveIntensity = 1.0;\r\n\t\tthis.emissiveMap = null;\r\n\r\n\t\tthis.specularMap = null;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.envMap = null;\r\n\t\tthis.combine = MultiplyOperation;\r\n\t\tthis.reflectivity = 1;\r\n\t\tthis.refractionRatio = 0.98;\r\n\r\n\t\tthis.wireframe = false;\r\n\t\tthis.wireframeLinewidth = 1;\r\n\t\tthis.wireframeLinecap = 'round';\r\n\t\tthis.wireframeLinejoin = 'round';\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshLambertMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshLambertMaterial.prototype.constructor = MeshLambertMaterial;\r\n\r\n\tMeshLambertMaterial.prototype.isMeshLambertMaterial = true;\r\n\r\n\tMeshLambertMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.lightMap = source.lightMap;\r\n\t\tthis.lightMapIntensity = source.lightMapIntensity;\r\n\r\n\t\tthis.aoMap = source.aoMap;\r\n\t\tthis.aoMapIntensity = source.aoMapIntensity;\r\n\r\n\t\tthis.emissive.copy( source.emissive );\r\n\t\tthis.emissiveMap = source.emissiveMap;\r\n\t\tthis.emissiveIntensity = source.emissiveIntensity;\r\n\r\n\t\tthis.specularMap = source.specularMap;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.envMap = source.envMap;\r\n\t\tthis.combine = source.combine;\r\n\t\tthis.reflectivity = source.reflectivity;\r\n\t\tthis.refractionRatio = source.refractionRatio;\r\n\r\n\t\tthis.wireframe = source.wireframe;\r\n\t\tthis.wireframeLinewidth = source.wireframeLinewidth;\r\n\t\tthis.wireframeLinecap = source.wireframeLinecap;\r\n\t\tthis.wireframeLinejoin = source.wireframeLinejoin;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * matcap: new THREE.Texture( ),\r\n\t *\r\n\t * map: new THREE.Texture( ),\r\n\t *\r\n\t * bumpMap: new THREE.Texture( ),\r\n\t * bumpScale: ,\r\n\t *\r\n\t * normalMap: new THREE.Texture( ),\r\n\t * normalMapType: THREE.TangentSpaceNormalMap,\r\n\t * normalScale: ,\r\n\t *\r\n\t * displacementMap: new THREE.Texture( ),\r\n\t * displacementScale: ,\r\n\t * displacementBias: ,\r\n\t *\r\n\t * alphaMap: new THREE.Texture( ),\r\n\t *\r\n\t * skinning: ,\r\n\t * morphTargets: ,\r\n\t * morphNormals: \r\n\t * }\r\n\t */\r\n\r\n\tfunction MeshMatcapMaterial( parameters ) {\r\n\r\n\t\tMaterial.call( this );\r\n\r\n\t\tthis.defines = { 'MATCAP': '' };\r\n\r\n\t\tthis.type = 'MeshMatcapMaterial';\r\n\r\n\t\tthis.color = new Color( 0xffffff ); // diffuse\r\n\r\n\t\tthis.matcap = null;\r\n\r\n\t\tthis.map = null;\r\n\r\n\t\tthis.bumpMap = null;\r\n\t\tthis.bumpScale = 1;\r\n\r\n\t\tthis.normalMap = null;\r\n\t\tthis.normalMapType = TangentSpaceNormalMap;\r\n\t\tthis.normalScale = new Vector2( 1, 1 );\r\n\r\n\t\tthis.displacementMap = null;\r\n\t\tthis.displacementScale = 1;\r\n\t\tthis.displacementBias = 0;\r\n\r\n\t\tthis.alphaMap = null;\r\n\r\n\t\tthis.skinning = false;\r\n\t\tthis.morphTargets = false;\r\n\t\tthis.morphNormals = false;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tMeshMatcapMaterial.prototype = Object.create( Material.prototype );\r\n\tMeshMatcapMaterial.prototype.constructor = MeshMatcapMaterial;\r\n\r\n\tMeshMatcapMaterial.prototype.isMeshMatcapMaterial = true;\r\n\r\n\tMeshMatcapMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.defines = { 'MATCAP': '' };\r\n\r\n\t\tthis.color.copy( source.color );\r\n\r\n\t\tthis.matcap = source.matcap;\r\n\r\n\t\tthis.map = source.map;\r\n\r\n\t\tthis.bumpMap = source.bumpMap;\r\n\t\tthis.bumpScale = source.bumpScale;\r\n\r\n\t\tthis.normalMap = source.normalMap;\r\n\t\tthis.normalMapType = source.normalMapType;\r\n\t\tthis.normalScale.copy( source.normalScale );\r\n\r\n\t\tthis.displacementMap = source.displacementMap;\r\n\t\tthis.displacementScale = source.displacementScale;\r\n\t\tthis.displacementBias = source.displacementBias;\r\n\r\n\t\tthis.alphaMap = source.alphaMap;\r\n\r\n\t\tthis.skinning = source.skinning;\r\n\t\tthis.morphTargets = source.morphTargets;\r\n\t\tthis.morphNormals = source.morphNormals;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t *\r\n\t * parameters = {\r\n\t * color: ,\r\n\t * opacity: ,\r\n\t *\r\n\t * linewidth: ,\r\n\t *\r\n\t * scale: ,\r\n\t * dashSize: ,\r\n\t * gapSize: \r\n\t * }\r\n\t */\r\n\r\n\tfunction LineDashedMaterial( parameters ) {\r\n\r\n\t\tLineBasicMaterial.call( this );\r\n\r\n\t\tthis.type = 'LineDashedMaterial';\r\n\r\n\t\tthis.scale = 1;\r\n\t\tthis.dashSize = 3;\r\n\t\tthis.gapSize = 1;\r\n\r\n\t\tthis.setValues( parameters );\r\n\r\n\t}\r\n\r\n\tLineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype );\r\n\tLineDashedMaterial.prototype.constructor = LineDashedMaterial;\r\n\r\n\tLineDashedMaterial.prototype.isLineDashedMaterial = true;\r\n\r\n\tLineDashedMaterial.prototype.copy = function ( source ) {\r\n\r\n\t\tLineBasicMaterial.prototype.copy.call( this, source );\r\n\r\n\t\tthis.scale = source.scale;\r\n\t\tthis.dashSize = source.dashSize;\r\n\t\tthis.gapSize = source.gapSize;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\n\n\tvar Materials = /*#__PURE__*/Object.freeze({\n\t\t__proto__: null,\n\t\tShadowMaterial: ShadowMaterial,\n\t\tSpriteMaterial: SpriteMaterial,\n\t\tRawShaderMaterial: RawShaderMaterial,\n\t\tShaderMaterial: ShaderMaterial,\n\t\tPointsMaterial: PointsMaterial,\n\t\tMeshPhysicalMaterial: MeshPhysicalMaterial,\n\t\tMeshStandardMaterial: MeshStandardMaterial,\n\t\tMeshPhongMaterial: MeshPhongMaterial,\n\t\tMeshToonMaterial: MeshToonMaterial,\n\t\tMeshNormalMaterial: MeshNormalMaterial,\n\t\tMeshLambertMaterial: MeshLambertMaterial,\n\t\tMeshDepthMaterial: MeshDepthMaterial,\n\t\tMeshDistanceMaterial: MeshDistanceMaterial,\n\t\tMeshBasicMaterial: MeshBasicMaterial,\n\t\tMeshMatcapMaterial: MeshMatcapMaterial,\n\t\tLineDashedMaterial: LineDashedMaterial,\n\t\tLineBasicMaterial: LineBasicMaterial,\n\t\tMaterial: Material\n\t});\n\n\t/**\r\n\t * @author tschw\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t */\r\n\r\n\tvar AnimationUtils = {\r\n\r\n\t\t// same as Array.prototype.slice, but also works on typed arrays\r\n\t\tarraySlice: function ( array, from, to ) {\r\n\r\n\t\t\tif ( AnimationUtils.isTypedArray( array ) ) {\r\n\r\n\t\t\t\t// in ios9 array.subarray(from, undefined) will return empty array\r\n\t\t\t\t// but array.subarray(from) or array.subarray(from, len) is correct\r\n\t\t\t\treturn new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn array.slice( from, to );\r\n\r\n\t\t},\r\n\r\n\t\t// converts an array to a specific type\r\n\t\tconvertArray: function ( array, type, forceClone ) {\r\n\r\n\t\t\tif ( ! array || // let 'undefined' and 'null' pass\r\n\t\t\t\t! forceClone && array.constructor === type ) { return array; }\r\n\r\n\t\t\tif ( typeof type.BYTES_PER_ELEMENT === 'number' ) {\r\n\r\n\t\t\t\treturn new type( array ); // create typed array\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn Array.prototype.slice.call( array ); // create Array\r\n\r\n\t\t},\r\n\r\n\t\tisTypedArray: function ( object ) {\r\n\r\n\t\t\treturn ArrayBuffer.isView( object ) &&\r\n\t\t\t\t! ( object instanceof DataView );\r\n\r\n\t\t},\r\n\r\n\t\t// returns an array by which times and values can be sorted\r\n\t\tgetKeyframeOrder: function ( times ) {\r\n\r\n\t\t\tfunction compareTime( i, j ) {\r\n\r\n\t\t\t\treturn times[ i ] - times[ j ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar n = times.length;\r\n\t\t\tvar result = new Array( n );\r\n\t\t\tfor ( var i = 0; i !== n; ++ i ) { result[ i ] = i; }\r\n\r\n\t\t\tresult.sort( compareTime );\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// uses the array previously returned by 'getKeyframeOrder' to sort data\r\n\t\tsortedArray: function ( values, stride, order ) {\r\n\r\n\t\t\tvar nValues = values.length;\r\n\t\t\tvar result = new values.constructor( nValues );\r\n\r\n\t\t\tfor ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) {\r\n\r\n\t\t\t\tvar srcOffset = order[ i ] * stride;\r\n\r\n\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\tresult[ dstOffset ++ ] = values[ srcOffset + j ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// function for parsing AOS keyframe formats\r\n\t\tflattenJSON: function ( jsonKeys, times, values, valuePropertyName ) {\r\n\r\n\t\t\tvar i = 1, key = jsonKeys[ 0 ];\r\n\r\n\t\t\twhile ( key !== undefined && key[ valuePropertyName ] === undefined ) {\r\n\r\n\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( key === undefined ) { return; } // no data\r\n\r\n\t\t\tvar value = key[ valuePropertyName ];\r\n\t\t\tif ( value === undefined ) { return; } // no data\r\n\r\n\t\t\tif ( Array.isArray( value ) ) {\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalues.push.apply( values, value ); // push all elements\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t} else if ( value.toArray !== undefined ) {\r\n\r\n\t\t\t\t// ...assume THREE.Math-ish\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalue.toArray( values, values.length );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// otherwise push as-is\r\n\r\n\t\t\t\tdo {\r\n\r\n\t\t\t\t\tvalue = key[ valuePropertyName ];\r\n\r\n\t\t\t\t\tif ( value !== undefined ) {\r\n\r\n\t\t\t\t\t\ttimes.push( key.time );\r\n\t\t\t\t\t\tvalues.push( value );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tkey = jsonKeys[ i ++ ];\r\n\r\n\t\t\t\t} while ( key !== undefined );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tsubclip: function ( sourceClip, name, startFrame, endFrame, fps ) {\r\n\r\n\t\t\tfps = fps || 30;\r\n\r\n\t\t\tvar clip = sourceClip.clone();\r\n\r\n\t\t\tclip.name = name;\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tvar track = clip.tracks[ i ];\r\n\t\t\t\tvar valueSize = track.getValueSize();\r\n\r\n\t\t\t\tvar times = [];\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\tfor ( var j = 0; j < track.times.length; ++ j ) {\r\n\r\n\t\t\t\t\tvar frame = track.times[ j ] * fps;\r\n\r\n\t\t\t\t\tif ( frame < startFrame || frame >= endFrame ) { continue; }\r\n\r\n\t\t\t\t\ttimes.push( track.times[ j ] );\r\n\r\n\t\t\t\t\tfor ( var k = 0; k < valueSize; ++ k ) {\r\n\r\n\t\t\t\t\t\tvalues.push( track.values[ j * valueSize + k ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( times.length === 0 ) { continue; }\r\n\r\n\t\t\t\ttrack.times = AnimationUtils.convertArray( times, track.times.constructor );\r\n\t\t\t\ttrack.values = AnimationUtils.convertArray( values, track.values.constructor );\r\n\r\n\t\t\t\ttracks.push( track );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tclip.tracks = tracks;\r\n\r\n\t\t\t// find minimum .times value across all tracks in the trimmed clip\r\n\r\n\t\t\tvar minStartTime = Infinity;\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tif ( minStartTime > clip.tracks[ i ].times[ 0 ] ) {\r\n\r\n\t\t\t\t\tminStartTime = clip.tracks[ i ].times[ 0 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// shift all tracks such that clip begins at t=0\r\n\r\n\t\t\tfor ( var i = 0; i < clip.tracks.length; ++ i ) {\r\n\r\n\t\t\t\tclip.tracks[ i ].shift( - 1 * minStartTime );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tclip.resetDuration();\r\n\r\n\t\t\treturn clip;\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * Abstract base class of interpolants over parametric samples.\r\n\t *\r\n\t * The parameter domain is one dimensional, typically the time or a path\r\n\t * along a curve defined by the data.\r\n\t *\r\n\t * The sample values can have any dimensionality and derived classes may\r\n\t * apply special interpretations to the data.\r\n\t *\r\n\t * This class provides the interval seek in a Template Method, deferring\r\n\t * the actual interpolation to derived classes.\r\n\t *\r\n\t * Time complexity is O(1) for linear access crossing at most two points\r\n\t * and O(log N) for random access, where N is the number of positions.\r\n\t *\r\n\t * References:\r\n\t *\r\n\t * \t\thttp://www.oodesign.com/template-method-pattern.html\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tthis.parameterPositions = parameterPositions;\r\n\t\tthis._cachedIndex = 0;\r\n\r\n\t\tthis.resultBuffer = resultBuffer !== undefined ?\r\n\t\t\tresultBuffer : new sampleValues.constructor( sampleSize );\r\n\t\tthis.sampleValues = sampleValues;\r\n\t\tthis.valueSize = sampleSize;\r\n\r\n\t}\r\n\r\n\tObject.assign( Interpolant.prototype, {\r\n\r\n\t\tevaluate: function ( t ) {\r\n\r\n\t\t\tvar pp = this.parameterPositions,\r\n\t\t\t\ti1 = this._cachedIndex,\r\n\r\n\t\t\t\tt1 = pp[ i1 ],\r\n\t\t\t\tt0 = pp[ i1 - 1 ];\r\n\r\n\t\t\tvalidate_interval: {\r\n\r\n\t\t\t\tseek: {\r\n\r\n\t\t\t\t\tvar right;\r\n\r\n\t\t\t\t\tlinear_scan: {\r\n\r\n\t\t\t\t\t\t//- See http://jsperf.com/comparison-to-undefined/3\r\n\t\t\t\t\t\t//- slower code:\r\n\t\t\t\t\t\t//-\r\n\t\t\t\t\t\t//- \t\t\t\tif ( t >= t1 || t1 === undefined ) {\r\n\t\t\t\t\t\tforward_scan: if ( ! ( t < t1 ) ) {\r\n\r\n\t\t\t\t\t\t\tfor ( var giveUpAt = i1 + 2; ; ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( t1 === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tif ( t < t0 ) { break forward_scan; }\r\n\r\n\t\t\t\t\t\t\t\t\t// after end\r\n\r\n\t\t\t\t\t\t\t\t\ti1 = pp.length;\r\n\t\t\t\t\t\t\t\t\tthis._cachedIndex = i1;\r\n\t\t\t\t\t\t\t\t\treturn this.afterEnd_( i1 - 1, t, t0 );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tif ( i1 === giveUpAt ) { break; } // this loop\r\n\r\n\t\t\t\t\t\t\t\tt0 = t1;\r\n\t\t\t\t\t\t\t\tt1 = pp[ ++ i1 ];\r\n\r\n\t\t\t\t\t\t\t\tif ( t < t1 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// we have arrived at the sought interval\r\n\t\t\t\t\t\t\t\t\tbreak seek;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// prepare binary search on the right side of the index\r\n\t\t\t\t\t\t\tright = pp.length;\r\n\t\t\t\t\t\t\tbreak linear_scan;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t//- slower code:\r\n\t\t\t\t\t\t//-\t\t\t\t\tif ( t < t0 || t0 === undefined ) {\r\n\t\t\t\t\t\tif ( ! ( t >= t0 ) ) {\r\n\r\n\t\t\t\t\t\t\t// looping?\r\n\r\n\t\t\t\t\t\t\tvar t1global = pp[ 1 ];\r\n\r\n\t\t\t\t\t\t\tif ( t < t1global ) {\r\n\r\n\t\t\t\t\t\t\t\ti1 = 2; // + 1, using the scan for the details\r\n\t\t\t\t\t\t\t\tt0 = t1global;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// linear reverse scan\r\n\r\n\t\t\t\t\t\t\tfor ( var giveUpAt = i1 - 2; ; ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( t0 === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// before start\r\n\r\n\t\t\t\t\t\t\t\t\tthis._cachedIndex = 0;\r\n\t\t\t\t\t\t\t\t\treturn this.beforeStart_( 0, t, t1 );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tif ( i1 === giveUpAt ) { break; } // this loop\r\n\r\n\t\t\t\t\t\t\t\tt1 = t0;\r\n\t\t\t\t\t\t\t\tt0 = pp[ -- i1 - 1 ];\r\n\r\n\t\t\t\t\t\t\t\tif ( t >= t0 ) {\r\n\r\n\t\t\t\t\t\t\t\t\t// we have arrived at the sought interval\r\n\t\t\t\t\t\t\t\t\tbreak seek;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t// prepare binary search on the left side of the index\r\n\t\t\t\t\t\t\tright = i1;\r\n\t\t\t\t\t\t\ti1 = 0;\r\n\t\t\t\t\t\t\tbreak linear_scan;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// the interval is valid\r\n\r\n\t\t\t\t\t\tbreak validate_interval;\r\n\r\n\t\t\t\t\t} // linear scan\r\n\r\n\t\t\t\t\t// binary search\r\n\r\n\t\t\t\t\twhile ( i1 < right ) {\r\n\r\n\t\t\t\t\t\tvar mid = ( i1 + right ) >>> 1;\r\n\r\n\t\t\t\t\t\tif ( t < pp[ mid ] ) {\r\n\r\n\t\t\t\t\t\t\tright = mid;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\ti1 = mid + 1;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tt1 = pp[ i1 ];\r\n\t\t\t\t\tt0 = pp[ i1 - 1 ];\r\n\r\n\t\t\t\t\t// check boundary cases, again\r\n\r\n\t\t\t\t\tif ( t0 === undefined ) {\r\n\r\n\t\t\t\t\t\tthis._cachedIndex = 0;\r\n\t\t\t\t\t\treturn this.beforeStart_( 0, t, t1 );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( t1 === undefined ) {\r\n\r\n\t\t\t\t\t\ti1 = pp.length;\r\n\t\t\t\t\t\tthis._cachedIndex = i1;\r\n\t\t\t\t\t\treturn this.afterEnd_( i1 - 1, t0, t );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} // seek\r\n\r\n\t\t\t\tthis._cachedIndex = i1;\r\n\r\n\t\t\t\tthis.intervalChanged_( i1, t0, t1 );\r\n\r\n\t\t\t} // validate_interval\r\n\r\n\t\t\treturn this.interpolate_( i1, t0, t, t1 );\r\n\r\n\t\t},\r\n\r\n\t\tsettings: null, // optional, subclass-specific settings structure\r\n\t\t// Note: The indirection allows central control of many interpolants.\r\n\r\n\t\t// --- Protected interface\r\n\r\n\t\tDefaultSettings_: {},\r\n\r\n\t\tgetSettings_: function () {\r\n\r\n\t\t\treturn this.settings || this.DefaultSettings_;\r\n\r\n\t\t},\r\n\r\n\t\tcopySampleValue_: function ( index ) {\r\n\r\n\t\t\t// copies a sample value to the result buffer\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\t\t\t\toffset = index * stride;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] = values[ offset + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t},\r\n\r\n\t\t// Template methods for derived classes:\r\n\r\n\t\tinterpolate_: function ( /* i1, t0, t, t1 */ ) {\r\n\r\n\t\t\tthrow new Error( 'call to abstract method' );\r\n\t\t\t// implementations shall return this.resultBuffer\r\n\r\n\t\t},\r\n\r\n\t\tintervalChanged_: function ( /* i1, t0, t1 */ ) {\r\n\r\n\t\t\t// empty\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//!\\ DECLARE ALIAS AFTER assign prototype !\r\n\tObject.assign( Interpolant.prototype, {\r\n\r\n\t\t//( 0, t, t0 ), returns this.resultBuffer\r\n\t\tbeforeStart_: Interpolant.prototype.copySampleValue_,\r\n\r\n\t\t//( N-1, tN-1, t ), returns this.resultBuffer\r\n\t\tafterEnd_: Interpolant.prototype.copySampleValue_,\r\n\r\n\t} );\n\n\t/**\r\n\t * Fast and simple cubic spline interpolant.\r\n\t *\r\n\t * It was derived from a Hermitian construction setting the first derivative\r\n\t * at each sample position to the linear slope between neighboring positions\r\n\t * over their parameter interval.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t\tthis._weightPrev = - 0;\r\n\t\tthis._offsetPrev = - 0;\r\n\t\tthis._weightNext = - 0;\r\n\t\tthis._offsetNext = - 0;\r\n\r\n\t}\r\n\r\n\tCubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: CubicInterpolant,\r\n\r\n\t\tDefaultSettings_: {\r\n\r\n\t\t\tendingStart: ZeroCurvatureEnding,\r\n\t\t\tendingEnd: ZeroCurvatureEnding\r\n\r\n\t\t},\r\n\r\n\t\tintervalChanged_: function ( i1, t0, t1 ) {\r\n\r\n\t\t\tvar pp = this.parameterPositions,\r\n\t\t\t\tiPrev = i1 - 2,\r\n\t\t\t\tiNext = i1 + 1,\r\n\r\n\t\t\t\ttPrev = pp[ iPrev ],\r\n\t\t\t\ttNext = pp[ iNext ];\r\n\r\n\t\t\tif ( tPrev === undefined ) {\r\n\r\n\t\t\t\tswitch ( this.getSettings_().endingStart ) {\r\n\r\n\t\t\t\t\tcase ZeroSlopeEnding:\r\n\r\n\t\t\t\t\t\t// f'(t0) = 0\r\n\t\t\t\t\t\tiPrev = i1;\r\n\t\t\t\t\t\ttPrev = 2 * t0 - t1;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase WrapAroundEnding:\r\n\r\n\t\t\t\t\t\t// use the other end of the curve\r\n\t\t\t\t\t\tiPrev = pp.length - 2;\r\n\t\t\t\t\t\ttPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault: // ZeroCurvatureEnding\r\n\r\n\t\t\t\t\t\t// f''(t0) = 0 a.k.a. Natural Spline\r\n\t\t\t\t\t\tiPrev = i1;\r\n\t\t\t\t\t\ttPrev = t1;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tNext === undefined ) {\r\n\r\n\t\t\t\tswitch ( this.getSettings_().endingEnd ) {\r\n\r\n\t\t\t\t\tcase ZeroSlopeEnding:\r\n\r\n\t\t\t\t\t\t// f'(tN) = 0\r\n\t\t\t\t\t\tiNext = i1;\r\n\t\t\t\t\t\ttNext = 2 * t1 - t0;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase WrapAroundEnding:\r\n\r\n\t\t\t\t\t\t// use the other end of the curve\r\n\t\t\t\t\t\tiNext = 1;\r\n\t\t\t\t\t\ttNext = t1 + pp[ 1 ] - pp[ 0 ];\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault: // ZeroCurvatureEnding\r\n\r\n\t\t\t\t\t\t// f''(tN) = 0, a.k.a. Natural Spline\r\n\t\t\t\t\t\tiNext = i1 - 1;\r\n\t\t\t\t\t\ttNext = t0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar halfDt = ( t1 - t0 ) * 0.5,\r\n\t\t\t\tstride = this.valueSize;\r\n\r\n\t\t\tthis._weightPrev = halfDt / ( t0 - tPrev );\r\n\t\t\tthis._weightNext = halfDt / ( tNext - t1 );\r\n\t\t\tthis._offsetPrev = iPrev * stride;\r\n\t\t\tthis._offsetNext = iNext * stride;\r\n\r\n\t\t},\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\to1 = i1 * stride,\t\to0 = o1 - stride,\r\n\t\t\t\toP = this._offsetPrev, \toN = this._offsetNext,\r\n\t\t\t\twP = this._weightPrev,\twN = this._weightNext,\r\n\r\n\t\t\t\tp = ( t - t0 ) / ( t1 - t0 ),\r\n\t\t\t\tpp = p * p,\r\n\t\t\t\tppp = pp * p;\r\n\r\n\t\t\t// evaluate polynomials\r\n\r\n\t\t\tvar sP = - wP * ppp + 2 * wP * pp - wP * p;\r\n\t\t\tvar s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1;\r\n\t\t\tvar s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p;\r\n\t\t\tvar sN = wN * ppp - wN * pp;\r\n\r\n\t\t\t// combine data linearly\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] =\r\n\t\t\t\t\t\tsP * values[ oP + i ] +\r\n\t\t\t\t\t\ts0 * values[ o0 + i ] +\r\n\t\t\t\t\t\ts1 * values[ o1 + i ] +\r\n\t\t\t\t\t\tsN * values[ oN + i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: LinearInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toffset1 = i1 * stride,\r\n\t\t\t\toffset0 = offset1 - stride,\r\n\r\n\t\t\t\tweight1 = ( t - t0 ) / ( t1 - t0 ),\r\n\t\t\t\tweight0 = 1 - weight1;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tresult[ i ] =\r\n\t\t\t\t\t\tvalues[ offset0 + i ] * weight0 +\r\n\t\t\t\t\t\tvalues[ offset1 + i ] * weight1;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Interpolant that evaluates to the sample value at the position preceeding\r\n\t * the parameter.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tDiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: DiscreteInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1 /*, t0, t, t1 */ ) {\r\n\r\n\t\t\treturn this.copySampleValue_( i1 - 1 );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A timed sequence of keyframes for a specific property.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction KeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tif ( name === undefined ) { throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); }\r\n\t\tif ( times === undefined || times.length === 0 ) { throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); }\r\n\r\n\t\tthis.name = name;\r\n\r\n\t\tthis.times = AnimationUtils.convertArray( times, this.TimeBufferType );\r\n\t\tthis.values = AnimationUtils.convertArray( values, this.ValueBufferType );\r\n\r\n\t\tthis.setInterpolation( interpolation || this.DefaultInterpolation );\r\n\r\n\t}\r\n\r\n\t// Static methods\r\n\r\n\tObject.assign( KeyframeTrack, {\r\n\r\n\t\t// Serialization (in static context, because of constructor invocation\r\n\t\t// and automatic invocation of .toJSON):\r\n\r\n\t\ttoJSON: function ( track ) {\r\n\r\n\t\t\tvar trackType = track.constructor;\r\n\r\n\t\t\tvar json;\r\n\r\n\t\t\t// derived classes can define a static toJSON method\r\n\t\t\tif ( trackType.toJSON !== undefined ) {\r\n\r\n\t\t\t\tjson = trackType.toJSON( track );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// by default, we assume the data can be serialized as-is\r\n\t\t\t\tjson = {\r\n\r\n\t\t\t\t\t'name': track.name,\r\n\t\t\t\t\t'times': AnimationUtils.convertArray( track.times, Array ),\r\n\t\t\t\t\t'values': AnimationUtils.convertArray( track.values, Array )\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar interpolation = track.getInterpolation();\r\n\r\n\t\t\t\tif ( interpolation !== track.DefaultInterpolation ) {\r\n\r\n\t\t\t\t\tjson.interpolation = interpolation;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tjson.type = track.ValueTypeName; // mandatory\r\n\r\n\t\t\treturn json;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( KeyframeTrack.prototype, {\r\n\r\n\t\tconstructor: KeyframeTrack,\r\n\r\n\t\tTimeBufferType: Float32Array,\r\n\r\n\t\tValueBufferType: Float32Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateLinear,\r\n\r\n\t\tInterpolantFactoryMethodDiscrete: function ( result ) {\r\n\r\n\t\t\treturn new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodLinear: function ( result ) {\r\n\r\n\t\t\treturn new LinearInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodSmooth: function ( result ) {\r\n\r\n\t\t\treturn new CubicInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tsetInterpolation: function ( interpolation ) {\r\n\r\n\t\t\tvar factoryMethod;\r\n\r\n\t\t\tswitch ( interpolation ) {\r\n\r\n\t\t\t\tcase InterpolateDiscrete:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodDiscrete;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase InterpolateLinear:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodLinear;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase InterpolateSmooth:\r\n\r\n\t\t\t\t\tfactoryMethod = this.InterpolantFactoryMethodSmooth;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( factoryMethod === undefined ) {\r\n\r\n\t\t\t\tvar message = \"unsupported interpolation for \" +\r\n\t\t\t\t\tthis.ValueTypeName + \" keyframe track named \" + this.name;\r\n\r\n\t\t\t\tif ( this.createInterpolant === undefined ) {\r\n\r\n\t\t\t\t\t// fall back to default, unless the default itself is messed up\r\n\t\t\t\t\tif ( interpolation !== this.DefaultInterpolation ) {\r\n\r\n\t\t\t\t\t\tthis.setInterpolation( this.DefaultInterpolation );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthrow new Error( message ); // fatal, in this case\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tconsole.warn( 'THREE.KeyframeTrack:', message );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.createInterpolant = factoryMethod;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetInterpolation: function () {\r\n\r\n\t\t\tswitch ( this.createInterpolant ) {\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodDiscrete:\r\n\r\n\t\t\t\t\treturn InterpolateDiscrete;\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodLinear:\r\n\r\n\t\t\t\t\treturn InterpolateLinear;\r\n\r\n\t\t\t\tcase this.InterpolantFactoryMethodSmooth:\r\n\r\n\t\t\t\t\treturn InterpolateSmooth;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tgetValueSize: function () {\r\n\r\n\t\t\treturn this.values.length / this.times.length;\r\n\r\n\t\t},\r\n\r\n\t\t// move all keyframes either forwards or backwards in time\r\n\t\tshift: function ( timeOffset ) {\r\n\r\n\t\t\tif ( timeOffset !== 0.0 ) {\r\n\r\n\t\t\t\tvar times = this.times;\r\n\r\n\t\t\t\tfor ( var i = 0, n = times.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\ttimes[ i ] += timeOffset;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// scale all keyframe times by a factor (useful for frame <-> seconds conversions)\r\n\t\tscale: function ( timeScale ) {\r\n\r\n\t\t\tif ( timeScale !== 1.0 ) {\r\n\r\n\t\t\t\tvar times = this.times;\r\n\r\n\t\t\t\tfor ( var i = 0, n = times.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\ttimes[ i ] *= timeScale;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// removes keyframes before and after animation without changing any values within the range [startTime, endTime].\r\n\t\t// IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values\r\n\t\ttrim: function ( startTime, endTime ) {\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tnKeys = times.length,\r\n\t\t\t\tfrom = 0,\r\n\t\t\t\tto = nKeys - 1;\r\n\r\n\t\t\twhile ( from !== nKeys && times[ from ] < startTime ) {\r\n\r\n\t\t\t\t++ from;\r\n\r\n\t\t\t}\r\n\r\n\t\t\twhile ( to !== - 1 && times[ to ] > endTime ) {\r\n\r\n\t\t\t\t-- to;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t++ to; // inclusive -> exclusive bound\r\n\r\n\t\t\tif ( from !== 0 || to !== nKeys ) {\r\n\r\n\t\t\t\t// empty tracks are forbidden, so keep at least one keyframe\r\n\t\t\t\tif ( from >= to ) { to = Math.max( to, 1 ), from = to - 1; }\r\n\r\n\t\t\t\tvar stride = this.getValueSize();\r\n\t\t\t\tthis.times = AnimationUtils.arraySlice( times, from, to );\r\n\t\t\t\tthis.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable\r\n\t\tvalidate: function () {\r\n\r\n\t\t\tvar valid = true;\r\n\r\n\t\t\tvar valueSize = this.getValueSize();\r\n\t\t\tif ( valueSize - Math.floor( valueSize ) !== 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Invalid value size in track.', this );\r\n\t\t\t\tvalid = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tvalues = this.values,\r\n\r\n\t\t\t\tnKeys = times.length;\r\n\r\n\t\t\tif ( nKeys === 0 ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Track is empty.', this );\r\n\t\t\t\tvalid = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar prevTime = null;\r\n\r\n\t\t\tfor ( var i = 0; i !== nKeys; i ++ ) {\r\n\r\n\t\t\t\tvar currTime = times[ i ];\r\n\r\n\t\t\t\tif ( typeof currTime === 'number' && isNaN( currTime ) ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime );\r\n\t\t\t\t\tvalid = false;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( prevTime !== null && prevTime > currTime ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime );\r\n\t\t\t\t\tvalid = false;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tprevTime = currTime;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( values !== undefined ) {\r\n\r\n\t\t\t\tif ( AnimationUtils.isTypedArray( values ) ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = values.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tvar value = values[ i ];\r\n\r\n\t\t\t\t\t\tif ( isNaN( value ) ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value );\r\n\t\t\t\t\t\t\tvalid = false;\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn valid;\r\n\r\n\t\t},\r\n\r\n\t\t// removes equivalent sequential keys as common in morph target sequences\r\n\t\t// (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0)\r\n\t\toptimize: function () {\r\n\r\n\t\t\tvar times = this.times,\r\n\t\t\t\tvalues = this.values,\r\n\t\t\t\tstride = this.getValueSize(),\r\n\r\n\t\t\t\tsmoothInterpolation = this.getInterpolation() === InterpolateSmooth,\r\n\r\n\t\t\t\twriteIndex = 1,\r\n\t\t\t\tlastIndex = times.length - 1;\r\n\r\n\t\t\tfor ( var i = 1; i < lastIndex; ++ i ) {\r\n\r\n\t\t\t\tvar keep = false;\r\n\r\n\t\t\t\tvar time = times[ i ];\r\n\t\t\t\tvar timeNext = times[ i + 1 ];\r\n\r\n\t\t\t\t// remove adjacent keyframes scheduled at the same time\r\n\r\n\t\t\t\tif ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) {\r\n\r\n\t\t\t\t\tif ( ! smoothInterpolation ) {\r\n\r\n\t\t\t\t\t\t// remove unnecessary keyframes same as their neighbors\r\n\r\n\t\t\t\t\t\tvar offset = i * stride,\r\n\t\t\t\t\t\t\toffsetP = offset - stride,\r\n\t\t\t\t\t\t\toffsetN = offset + stride;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar value = values[ offset + j ];\r\n\r\n\t\t\t\t\t\t\tif ( value !== values[ offsetP + j ] ||\r\n\t\t\t\t\t\t\t\tvalue !== values[ offsetN + j ] ) {\r\n\r\n\t\t\t\t\t\t\t\tkeep = true;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tkeep = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// in-place compaction\r\n\r\n\t\t\t\tif ( keep ) {\r\n\r\n\t\t\t\t\tif ( i !== writeIndex ) {\r\n\r\n\t\t\t\t\t\ttimes[ writeIndex ] = times[ i ];\r\n\r\n\t\t\t\t\t\tvar readOffset = i * stride,\r\n\t\t\t\t\t\t\twriteOffset = writeIndex * stride;\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvalues[ writeOffset + j ] = values[ readOffset + j ];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t++ writeIndex;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// flush last keyframe (compaction looks ahead)\r\n\r\n\t\t\tif ( lastIndex > 0 ) {\r\n\r\n\t\t\t\ttimes[ writeIndex ] = times[ lastIndex ];\r\n\r\n\t\t\t\tfor ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) {\r\n\r\n\t\t\t\t\tvalues[ writeOffset + j ] = values[ readOffset + j ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t++ writeIndex;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( writeIndex !== times.length ) {\r\n\r\n\t\t\t\tthis.times = AnimationUtils.arraySlice( times, 0, writeIndex );\r\n\t\t\t\tthis.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\tvar times = AnimationUtils.arraySlice( this.times, 0 );\r\n\t\t\tvar values = AnimationUtils.arraySlice( this.values, 0 );\r\n\r\n\t\t\tvar TypedKeyframeTrack = this.constructor;\r\n\t\t\tvar track = new TypedKeyframeTrack( this.name, times, values );\r\n\r\n\t\t\t// Interpolant argument to constructor is not saved, so copy the factory method directly.\r\n\t\t\ttrack.createInterpolant = this.createInterpolant;\r\n\r\n\t\t\treturn track;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of Boolean keyframe values.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction BooleanKeyframeTrack( name, times, values ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values );\r\n\r\n\t}\r\n\r\n\tBooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: BooleanKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'bool',\r\n\t\tValueBufferType: Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateDiscrete,\r\n\r\n\t\tInterpolantFactoryMethodLinear: undefined,\r\n\t\tInterpolantFactoryMethodSmooth: undefined\r\n\r\n\t\t// Note: Actually this track could have a optimized / compressed\r\n\t\t// representation of a single value and a custom interpolant that\r\n\t\t// computes \"firstValue ^ isOdd( index )\".\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of keyframe values that represent color.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction ColorKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: ColorKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'color'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t\t// Note: Very basic implementation and nothing special yet.\r\n\t\t// However, this is the place for color space parameterization.\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of numeric keyframe values.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction NumberKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tNumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: NumberKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'number'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t} );\n\n\t/**\r\n\t * Spherical linear unit quaternion interpolant.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tInterpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tQuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), {\r\n\r\n\t\tconstructor: QuaternionLinearInterpolant,\r\n\r\n\t\tinterpolate_: function ( i1, t0, t, t1 ) {\r\n\r\n\t\t\tvar result = this.resultBuffer,\r\n\t\t\t\tvalues = this.sampleValues,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toffset = i1 * stride,\r\n\r\n\t\t\t\talpha = ( t - t0 ) / ( t1 - t0 );\r\n\r\n\t\t\tfor ( var end = offset + stride; offset !== end; offset += 4 ) {\r\n\r\n\t\t\t\tQuaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn result;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of quaternion keyframe values.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction QuaternionKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tQuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: QuaternionKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'quaternion',\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\tDefaultInterpolation: InterpolateLinear,\r\n\r\n\t\tInterpolantFactoryMethodLinear: function ( result ) {\r\n\r\n\t\t\treturn new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );\r\n\r\n\t\t},\r\n\r\n\t\tInterpolantFactoryMethodSmooth: undefined // not yet implemented\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track that interpolates Strings\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction StringKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tStringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: StringKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'string',\r\n\t\tValueBufferType: Array,\r\n\r\n\t\tDefaultInterpolation: InterpolateDiscrete,\r\n\r\n\t\tInterpolantFactoryMethodLinear: undefined,\r\n\r\n\t\tInterpolantFactoryMethodSmooth: undefined\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A Track of vectored keyframe values.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction VectorKeyframeTrack( name, times, values, interpolation ) {\r\n\r\n\t\tKeyframeTrack.call( this, name, times, values, interpolation );\r\n\r\n\t}\r\n\r\n\tVectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), {\r\n\r\n\t\tconstructor: VectorKeyframeTrack,\r\n\r\n\t\tValueTypeName: 'vector'\r\n\r\n\t\t// ValueBufferType is inherited\r\n\r\n\t\t// DefaultInterpolation is inherited\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Reusable set of Tracks that represent an animation.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t */\r\n\r\n\tfunction AnimationClip( name, duration, tracks ) {\r\n\r\n\t\tthis.name = name;\r\n\t\tthis.tracks = tracks;\r\n\t\tthis.duration = ( duration !== undefined ) ? duration : - 1;\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\t// this means it should figure out its duration by scanning the tracks\r\n\t\tif ( this.duration < 0 ) {\r\n\r\n\t\t\tthis.resetDuration();\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction getTrackTypeForValueTypeName( typeName ) {\r\n\r\n\t\tswitch ( typeName.toLowerCase() ) {\r\n\r\n\t\t\tcase 'scalar':\r\n\t\t\tcase 'double':\r\n\t\t\tcase 'float':\r\n\t\t\tcase 'number':\r\n\t\t\tcase 'integer':\r\n\r\n\t\t\t\treturn NumberKeyframeTrack;\r\n\r\n\t\t\tcase 'vector':\r\n\t\t\tcase 'vector2':\r\n\t\t\tcase 'vector3':\r\n\t\t\tcase 'vector4':\r\n\r\n\t\t\t\treturn VectorKeyframeTrack;\r\n\r\n\t\t\tcase 'color':\r\n\r\n\t\t\t\treturn ColorKeyframeTrack;\r\n\r\n\t\t\tcase 'quaternion':\r\n\r\n\t\t\t\treturn QuaternionKeyframeTrack;\r\n\r\n\t\t\tcase 'bool':\r\n\t\t\tcase 'boolean':\r\n\r\n\t\t\t\treturn BooleanKeyframeTrack;\r\n\r\n\t\t\tcase 'string':\r\n\r\n\t\t\t\treturn StringKeyframeTrack;\r\n\r\n\t\t}\r\n\r\n\t\tthrow new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );\r\n\r\n\t}\r\n\r\n\tfunction parseKeyframeTrack( json ) {\r\n\r\n\t\tif ( json.type === undefined ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' );\r\n\r\n\t\t}\r\n\r\n\t\tvar trackType = getTrackTypeForValueTypeName( json.type );\r\n\r\n\t\tif ( json.times === undefined ) {\r\n\r\n\t\t\tvar times = [], values = [];\r\n\r\n\t\t\tAnimationUtils.flattenJSON( json.keys, times, values, 'value' );\r\n\r\n\t\t\tjson.times = times;\r\n\t\t\tjson.values = values;\r\n\r\n\t\t}\r\n\r\n\t\t// derived classes can define a static parse method\r\n\t\tif ( trackType.parse !== undefined ) {\r\n\r\n\t\t\treturn trackType.parse( json );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// by default, we assume a constructor compatible with the base\r\n\t\t\treturn new trackType( json.name, json.times, json.values, json.interpolation );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationClip, {\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar tracks = [],\r\n\t\t\t\tjsonTracks = json.tracks,\r\n\t\t\t\tframeTime = 1.0 / ( json.fps || 1.0 );\r\n\r\n\t\t\tfor ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\ttracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( json.name, json.duration, tracks );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( clip ) {\r\n\r\n\t\t\tvar tracks = [],\r\n\t\t\t\tclipTracks = clip.tracks;\r\n\r\n\t\t\tvar json = {\r\n\r\n\t\t\t\t'name': clip.name,\r\n\t\t\t\t'duration': clip.duration,\r\n\t\t\t\t'tracks': tracks,\r\n\t\t\t\t'uuid': clip.uuid\r\n\r\n\t\t\t};\r\n\r\n\t\t\tfor ( var i = 0, n = clipTracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\ttracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn json;\r\n\r\n\t\t},\r\n\r\n\t\tCreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) {\r\n\r\n\t\t\tvar numMorphTargets = morphTargetSequence.length;\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < numMorphTargets; i ++ ) {\r\n\r\n\t\t\t\tvar times = [];\r\n\t\t\t\tvar values = [];\r\n\r\n\t\t\t\ttimes.push(\r\n\t\t\t\t\t( i + numMorphTargets - 1 ) % numMorphTargets,\r\n\t\t\t\t\ti,\r\n\t\t\t\t\t( i + 1 ) % numMorphTargets );\r\n\r\n\t\t\t\tvalues.push( 0, 1, 0 );\r\n\r\n\t\t\t\tvar order = AnimationUtils.getKeyframeOrder( times );\r\n\t\t\t\ttimes = AnimationUtils.sortedArray( times, 1, order );\r\n\t\t\t\tvalues = AnimationUtils.sortedArray( values, 1, order );\r\n\r\n\t\t\t\t// if there is a key at the first frame, duplicate it as the\r\n\t\t\t\t// last frame as well for perfect loop.\r\n\t\t\t\tif ( ! noLoop && times[ 0 ] === 0 ) {\r\n\r\n\t\t\t\t\ttimes.push( numMorphTargets );\r\n\t\t\t\t\tvalues.push( values[ 0 ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttracks.push(\r\n\t\t\t\t\tnew NumberKeyframeTrack(\r\n\t\t\t\t\t\t'.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']',\r\n\t\t\t\t\t\ttimes, values\r\n\t\t\t\t\t).scale( 1.0 / fps ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( name, - 1, tracks );\r\n\r\n\t\t},\r\n\r\n\t\tfindByName: function ( objectOrClipArray, name ) {\r\n\r\n\t\t\tvar clipArray = objectOrClipArray;\r\n\r\n\t\t\tif ( ! Array.isArray( objectOrClipArray ) ) {\r\n\r\n\t\t\t\tvar o = objectOrClipArray;\r\n\t\t\t\tclipArray = o.geometry && o.geometry.animations || o.animations;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < clipArray.length; i ++ ) {\r\n\r\n\t\t\t\tif ( clipArray[ i ].name === name ) {\r\n\r\n\t\t\t\t\treturn clipArray[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\tCreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) {\r\n\r\n\t\t\tvar animationToMorphTargets = {};\r\n\r\n\t\t\t// tested with https://regex101.com/ on trick sequences\r\n\t\t\t// such flamingo_flyA_003, flamingo_run1_003, crdeath0059\r\n\t\t\tvar pattern = /^([\\w-]*?)([\\d]+)$/;\r\n\r\n\t\t\t// sort morph target names into animation groups based\r\n\t\t\t// patterns like Walk_001, Walk_002, Run_001, Run_002\r\n\t\t\tfor ( var i = 0, il = morphTargets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar morphTarget = morphTargets[ i ];\r\n\t\t\t\tvar parts = morphTarget.name.match( pattern );\r\n\r\n\t\t\t\tif ( parts && parts.length > 1 ) {\r\n\r\n\t\t\t\t\tvar name = parts[ 1 ];\r\n\r\n\t\t\t\t\tvar animationMorphTargets = animationToMorphTargets[ name ];\r\n\t\t\t\t\tif ( ! animationMorphTargets ) {\r\n\r\n\t\t\t\t\t\tanimationToMorphTargets[ name ] = animationMorphTargets = [];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tanimationMorphTargets.push( morphTarget );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar clips = [];\r\n\r\n\t\t\tfor ( var name in animationToMorphTargets ) {\r\n\r\n\t\t\t\tclips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn clips;\r\n\r\n\t\t},\r\n\r\n\t\t// parse the animation.hierarchy format\r\n\t\tparseAnimation: function ( animation, bones ) {\r\n\r\n\t\t\tif ( ! animation ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.AnimationClip: No animation in JSONLoader data.' );\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) {\r\n\r\n\t\t\t\t// only return track if there are actually keys.\r\n\t\t\t\tif ( animationKeys.length !== 0 ) {\r\n\r\n\t\t\t\t\tvar times = [];\r\n\t\t\t\t\tvar values = [];\r\n\r\n\t\t\t\t\tAnimationUtils.flattenJSON( animationKeys, times, values, propertyName );\r\n\r\n\t\t\t\t\t// empty keys are filtered out, so check again\r\n\t\t\t\t\tif ( times.length !== 0 ) {\r\n\r\n\t\t\t\t\t\tdestTracks.push( new trackType( trackName, times, values ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tvar clipName = animation.name || 'default';\r\n\t\t\t// automatic length determination in AnimationClip.\r\n\t\t\tvar duration = animation.length || - 1;\r\n\t\t\tvar fps = animation.fps || 30;\r\n\r\n\t\t\tvar hierarchyTracks = animation.hierarchy || [];\r\n\r\n\t\t\tfor ( var h = 0; h < hierarchyTracks.length; h ++ ) {\r\n\r\n\t\t\t\tvar animationKeys = hierarchyTracks[ h ].keys;\r\n\r\n\t\t\t\t// skip empty tracks\r\n\t\t\t\tif ( ! animationKeys || animationKeys.length === 0 ) { continue; }\r\n\r\n\t\t\t\t// process morph targets\r\n\t\t\t\tif ( animationKeys[ 0 ].morphTargets ) {\r\n\r\n\t\t\t\t\t// figure out all morph targets used in this track\r\n\t\t\t\t\tvar morphTargetNames = {};\r\n\r\n\t\t\t\t\tfor ( var k = 0; k < animationKeys.length; k ++ ) {\r\n\r\n\t\t\t\t\t\tif ( animationKeys[ k ].morphTargets ) {\r\n\r\n\t\t\t\t\t\t\tfor ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tmorphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// create a track for each morph target with all zero\r\n\t\t\t\t\t// morphTargetInfluences except for the keys in which\r\n\t\t\t\t\t// the morphTarget is named.\r\n\t\t\t\t\tfor ( var morphTargetName in morphTargetNames ) {\r\n\r\n\t\t\t\t\t\tvar times = [];\r\n\t\t\t\t\t\tvar values = [];\r\n\r\n\t\t\t\t\t\tfor ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) {\r\n\r\n\t\t\t\t\t\t\tvar animationKey = animationKeys[ k ];\r\n\r\n\t\t\t\t\t\t\ttimes.push( animationKey.time );\r\n\t\t\t\t\t\t\tvalues.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tduration = morphTargetNames.length * ( fps || 1.0 );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// ...assume skeletal animation\r\n\r\n\t\t\t\t\tvar boneName = '.bones[' + bones[ h ].name + ']';\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tVectorKeyframeTrack, boneName + '.position',\r\n\t\t\t\t\t\tanimationKeys, 'pos', tracks );\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tQuaternionKeyframeTrack, boneName + '.quaternion',\r\n\t\t\t\t\t\tanimationKeys, 'rot', tracks );\r\n\r\n\t\t\t\t\taddNonemptyTrack(\r\n\t\t\t\t\t\tVectorKeyframeTrack, boneName + '.scale',\r\n\t\t\t\t\t\tanimationKeys, 'scl', tracks );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tracks.length === 0 ) {\r\n\r\n\t\t\t\treturn null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar clip = new AnimationClip( clipName, duration, tracks );\r\n\r\n\t\t\treturn clip;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( AnimationClip.prototype, {\r\n\r\n\t\tresetDuration: function () {\r\n\r\n\t\t\tvar tracks = this.tracks, duration = 0;\r\n\r\n\t\t\tfor ( var i = 0, n = tracks.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar track = this.tracks[ i ];\r\n\r\n\t\t\t\tduration = Math.max( duration, track.times[ track.times.length - 1 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.duration = duration;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttrim: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tthis.tracks[ i ].trim( 0, this.duration );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tvalidate: function () {\r\n\r\n\t\t\tvar valid = true;\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tvalid = valid && this.tracks[ i ].validate();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn valid;\r\n\r\n\t\t},\r\n\r\n\t\toptimize: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\tthis.tracks[ i ].optimize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0; i < this.tracks.length; i ++ ) {\r\n\r\n\t\t\t\ttracks.push( this.tracks[ i ].clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new AnimationClip( this.name, this.duration, tracks );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar Cache = {\r\n\r\n\t\tenabled: false,\r\n\r\n\t\tfiles: {},\r\n\r\n\t\tadd: function ( key, file ) {\r\n\r\n\t\t\tif ( this.enabled === false ) { return; }\r\n\r\n\t\t\t// console.log( 'THREE.Cache', 'Adding key:', key );\r\n\r\n\t\t\tthis.files[ key ] = file;\r\n\r\n\t\t},\r\n\r\n\t\tget: function ( key ) {\r\n\r\n\t\t\tif ( this.enabled === false ) { return; }\r\n\r\n\t\t\t// console.log( 'THREE.Cache', 'Checking key:', key );\r\n\r\n\t\t\treturn this.files[ key ];\r\n\r\n\t\t},\r\n\r\n\t\tremove: function ( key ) {\r\n\r\n\t\t\tdelete this.files[ key ];\r\n\r\n\t\t},\r\n\r\n\t\tclear: function () {\r\n\r\n\t\t\tthis.files = {};\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction LoadingManager( onLoad, onProgress, onError ) {\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar isLoading = false;\r\n\t\tvar itemsLoaded = 0;\r\n\t\tvar itemsTotal = 0;\r\n\t\tvar urlModifier = undefined;\r\n\t\tvar handlers = [];\r\n\r\n\t\t// Refer to #5689 for the reason why we don't set .onStart\r\n\t\t// in the constructor\r\n\r\n\t\tthis.onStart = undefined;\r\n\t\tthis.onLoad = onLoad;\r\n\t\tthis.onProgress = onProgress;\r\n\t\tthis.onError = onError;\r\n\r\n\t\tthis.itemStart = function ( url ) {\r\n\r\n\t\t\titemsTotal ++;\r\n\r\n\t\t\tif ( isLoading === false ) {\r\n\r\n\t\t\t\tif ( scope.onStart !== undefined ) {\r\n\r\n\t\t\t\t\tscope.onStart( url, itemsLoaded, itemsTotal );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tisLoading = true;\r\n\r\n\t\t};\r\n\r\n\t\tthis.itemEnd = function ( url ) {\r\n\r\n\t\t\titemsLoaded ++;\r\n\r\n\t\t\tif ( scope.onProgress !== undefined ) {\r\n\r\n\t\t\t\tscope.onProgress( url, itemsLoaded, itemsTotal );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( itemsLoaded === itemsTotal ) {\r\n\r\n\t\t\t\tisLoading = false;\r\n\r\n\t\t\t\tif ( scope.onLoad !== undefined ) {\r\n\r\n\t\t\t\t\tscope.onLoad();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.itemError = function ( url ) {\r\n\r\n\t\t\tif ( scope.onError !== undefined ) {\r\n\r\n\t\t\t\tscope.onError( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t\tthis.resolveURL = function ( url ) {\r\n\r\n\t\t\tif ( urlModifier ) {\r\n\r\n\t\t\t\treturn urlModifier( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn url;\r\n\r\n\t\t};\r\n\r\n\t\tthis.setURLModifier = function ( transform ) {\r\n\r\n\t\t\turlModifier = transform;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.addHandler = function ( regex, loader ) {\r\n\r\n\t\t\thandlers.push( regex, loader );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.removeHandler = function ( regex ) {\r\n\r\n\t\t\tvar index = handlers.indexOf( regex );\r\n\r\n\t\t\tif ( index !== - 1 ) {\r\n\r\n\t\t\t\thandlers.splice( index, 2 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t};\r\n\r\n\t\tthis.getHandler = function ( file ) {\r\n\r\n\t\t\tfor ( var i = 0, l = handlers.length; i < l; i += 2 ) {\r\n\r\n\t\t\t\tvar regex = handlers[ i ];\r\n\t\t\t\tvar loader = handlers[ i + 1 ];\r\n\r\n\t\t\t\tif ( regex.global ) { regex.lastIndex = 0; } // see #17920\r\n\r\n\t\t\t\tif ( regex.test( file ) ) {\r\n\r\n\t\t\t\t\treturn loader;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tvar DefaultLoadingManager = new LoadingManager();\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Loader( manager ) {\r\n\r\n\t\tthis.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;\r\n\r\n\t\tthis.crossOrigin = 'anonymous';\r\n\t\tthis.path = '';\r\n\t\tthis.resourcePath = '';\r\n\r\n\t}\r\n\r\n\tObject.assign( Loader.prototype, {\r\n\r\n\t\tload: function ( /* url, onLoad, onProgress, onError */ ) {},\r\n\r\n\t\tparse: function ( /* data */ ) {},\r\n\r\n\t\tsetCrossOrigin: function ( crossOrigin ) {\r\n\r\n\t\t\tthis.crossOrigin = crossOrigin;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetPath: function ( path ) {\r\n\r\n\t\t\tthis.path = path;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetResourcePath: function ( resourcePath ) {\r\n\r\n\t\t\tthis.resourcePath = resourcePath;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar loading = {};\r\n\r\n\tfunction FileLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tFileLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: FileLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( url === undefined ) { url = ''; }\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Check if request is duplicate\r\n\r\n\t\t\tif ( loading[ url ] !== undefined ) {\r\n\r\n\t\t\t\tloading[ url ].push( {\r\n\r\n\t\t\t\t\tonLoad: onLoad,\r\n\t\t\t\t\tonProgress: onProgress,\r\n\t\t\t\t\tonError: onError\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Check for data: URI\r\n\t\t\tvar dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\r\n\t\t\tvar dataUriRegexResult = url.match( dataUriRegex );\r\n\r\n\t\t\t// Safari can not handle Data URIs through XMLHttpRequest so process manually\r\n\t\t\tif ( dataUriRegexResult ) {\r\n\r\n\t\t\t\tvar mimeType = dataUriRegexResult[ 1 ];\r\n\t\t\t\tvar isBase64 = !! dataUriRegexResult[ 2 ];\r\n\t\t\t\tvar data = dataUriRegexResult[ 3 ];\r\n\r\n\t\t\t\tdata = decodeURIComponent( data );\r\n\r\n\t\t\t\tif ( isBase64 ) { data = atob( data ); }\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tvar response;\r\n\t\t\t\t\tvar responseType = ( this.responseType || '' ).toLowerCase();\r\n\r\n\t\t\t\t\tswitch ( responseType ) {\r\n\r\n\t\t\t\t\t\tcase 'arraybuffer':\r\n\t\t\t\t\t\tcase 'blob':\r\n\r\n\t\t\t\t\t\t\tvar view = new Uint8Array( data.length );\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0; i < data.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tview[ i ] = data.charCodeAt( i );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tif ( responseType === 'blob' ) {\r\n\r\n\t\t\t\t\t\t\t\tresponse = new Blob( [ view.buffer ], { type: mimeType } );\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tresponse = view.buffer;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'document':\r\n\r\n\t\t\t\t\t\t\tvar parser = new DOMParser();\r\n\t\t\t\t\t\t\tresponse = parser.parseFromString( data, mimeType );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'json':\r\n\r\n\t\t\t\t\t\t\tresponse = JSON.parse( data );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault: // 'text' or other\r\n\r\n\t\t\t\t\t\t\tresponse = data;\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Wait for next browser tick like standard XMLHttpRequest event dispatching does\r\n\t\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( response ); }\r\n\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}, 0 );\r\n\r\n\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\t// Wait for next browser tick like standard XMLHttpRequest event dispatching does\r\n\t\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\t\tif ( onError ) { onError( error ); }\r\n\r\n\t\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}, 0 );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// Initialise array for duplicate requests\r\n\r\n\t\t\t\tloading[ url ] = [];\r\n\r\n\t\t\t\tloading[ url ].push( {\r\n\r\n\t\t\t\t\tonLoad: onLoad,\r\n\t\t\t\t\tonProgress: onProgress,\r\n\t\t\t\t\tonError: onError\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t\tvar request = new XMLHttpRequest();\r\n\r\n\t\t\t\trequest.open( 'GET', url, true );\r\n\r\n\t\t\t\trequest.addEventListener( 'load', function ( event ) {\r\n\r\n\t\t\t\t\tvar response = this.response;\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tif ( this.status === 200 || this.status === 0 ) {\r\n\r\n\t\t\t\t\t\t// Some browsers return HTTP Status 0 when using non-http protocol\r\n\t\t\t\t\t\t// e.g. 'file://' or 'data://'. Handle as success.\r\n\r\n\t\t\t\t\t\tif ( this.status === 0 ) { console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); }\r\n\r\n\t\t\t\t\t\t// Add to cache only on HTTP success, so that we do not cache\r\n\t\t\t\t\t\t// error response bodies as proper responses to requests.\r\n\t\t\t\t\t\tCache.add( url, response );\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\t\tif ( callback.onLoad ) { callback.onLoad( response ); }\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'progress', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onProgress ) { callback.onProgress( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'error', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\trequest.addEventListener( 'abort', function ( event ) {\r\n\r\n\t\t\t\t\tvar callbacks = loading[ url ];\r\n\r\n\t\t\t\t\tdelete loading[ url ];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = callbacks.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar callback = callbacks[ i ];\r\n\t\t\t\t\t\tif ( callback.onError ) { callback.onError( event ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, false );\r\n\r\n\t\t\t\tif ( this.responseType !== undefined ) { request.responseType = this.responseType; }\r\n\t\t\t\tif ( this.withCredentials !== undefined ) { request.withCredentials = this.withCredentials; }\r\n\r\n\t\t\t\tif ( request.overrideMimeType ) { request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); }\r\n\r\n\t\t\t\tfor ( var header in this.requestHeader ) {\r\n\r\n\t\t\t\t\trequest.setRequestHeader( header, this.requestHeader[ header ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\trequest.send( null );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\treturn request;\r\n\r\n\t\t},\r\n\r\n\t\tsetResponseType: function ( value ) {\r\n\r\n\t\t\tthis.responseType = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetWithCredentials: function ( value ) {\r\n\r\n\t\t\tthis.withCredentials = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMimeType: function ( value ) {\r\n\r\n\t\t\tthis.mimeType = value;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetRequestHeader: function ( value ) {\r\n\r\n\t\t\tthis.requestHeader = value;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io/\r\n\t */\r\n\r\n\tfunction AnimationLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tAnimationLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: AnimationLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar animations = [];\r\n\r\n\t\t\tfor ( var i = 0; i < json.length; i ++ ) {\r\n\r\n\t\t\t\tvar clip = AnimationClip.parse( json[ i ] );\r\n\r\n\t\t\t\tanimations.push( clip );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn animations;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t *\r\n\t * Abstract Base class to block based textures loader (dds, pvr, ...)\r\n\t *\r\n\t * Sub classes have to implement the parse() method which will be used in load().\r\n\t */\r\n\r\n\tfunction CompressedTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tCompressedTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: CompressedTextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar images = [];\r\n\r\n\t\t\tvar texture = new CompressedTexture();\r\n\t\t\ttexture.image = images;\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\r\n\t\t\tfunction loadTexture( i ) {\r\n\r\n\t\t\t\tloader.load( url[ i ], function ( buffer ) {\r\n\r\n\t\t\t\t\tvar texDatas = scope.parse( buffer, true );\r\n\r\n\t\t\t\t\timages[ i ] = {\r\n\t\t\t\t\t\twidth: texDatas.width,\r\n\t\t\t\t\t\theight: texDatas.height,\r\n\t\t\t\t\t\tformat: texDatas.format,\r\n\t\t\t\t\t\tmipmaps: texDatas.mipmaps\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t\tloaded += 1;\r\n\r\n\t\t\t\t\tif ( loaded === 6 ) {\r\n\r\n\t\t\t\t\t\tif ( texDatas.mipmapCount === 1 )\r\n\t\t\t\t\t\t\t{ texture.minFilter = LinearFilter; }\r\n\r\n\t\t\t\t\t\ttexture.format = texDatas.format;\r\n\t\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, onProgress, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( Array.isArray( url ) ) {\r\n\r\n\t\t\t\tvar loaded = 0;\r\n\r\n\t\t\t\tfor ( var i = 0, il = url.length; i < il; ++ i ) {\r\n\r\n\t\t\t\t\tloadTexture( i );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// compressed cubemap texture stored in a single DDS file\r\n\r\n\t\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\t\tvar texDatas = scope.parse( buffer, true );\r\n\r\n\t\t\t\t\tif ( texDatas.isCubemap ) {\r\n\r\n\t\t\t\t\t\tvar faces = texDatas.mipmaps.length / texDatas.mipmapCount;\r\n\r\n\t\t\t\t\t\tfor ( var f = 0; f < faces; f ++ ) {\r\n\r\n\t\t\t\t\t\t\timages[ f ] = { mipmaps: [] };\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0; i < texDatas.mipmapCount; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\timages[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );\r\n\t\t\t\t\t\t\t\timages[ f ].format = texDatas.format;\r\n\t\t\t\t\t\t\t\timages[ f ].width = texDatas.width;\r\n\t\t\t\t\t\t\t\timages[ f ].height = texDatas.height;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ttexture.image.width = texDatas.width;\r\n\t\t\t\t\t\ttexture.image.height = texDatas.height;\r\n\t\t\t\t\t\ttexture.mipmaps = texDatas.mipmaps;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( texDatas.mipmapCount === 1 ) {\r\n\r\n\t\t\t\t\t\ttexture.minFilter = LinearFilter;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.format = texDatas.format;\r\n\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t}, onProgress, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Nikos M. / https://github.com/foo123/\r\n\t *\r\n\t * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)\r\n\t *\r\n\t * Sub classes have to implement the parse() method which will be used in load().\r\n\t */\r\n\r\n\tfunction DataTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tDataTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: DataTextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar texture = new DataTexture();\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\tvar texData = scope.parse( buffer );\r\n\r\n\t\t\t\tif ( ! texData ) { return; }\r\n\r\n\t\t\t\tif ( texData.image !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.image = texData.image;\r\n\r\n\t\t\t\t} else if ( texData.data !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.image.width = texData.width;\r\n\t\t\t\t\ttexture.image.height = texData.height;\r\n\t\t\t\t\ttexture.image.data = texData.data;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;\r\n\t\t\t\ttexture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;\r\n\r\n\t\t\t\ttexture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;\r\n\t\t\t\ttexture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;\r\n\r\n\t\t\t\ttexture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;\r\n\r\n\t\t\t\tif ( texData.format !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.format = texData.format;\r\n\r\n\t\t\t\t}\r\n\t\t\t\tif ( texData.type !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.type = texData.type;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texData.mipmaps !== undefined ) {\r\n\r\n\t\t\t\t\ttexture.mipmaps = texData.mipmaps;\r\n\t\t\t\t\ttexture.minFilter = LinearMipmapLinearFilter; // presumably...\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( texData.mipmapCount === 1 ) {\r\n\r\n\t\t\t\t\ttexture.minFilter = LinearFilter;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( texture, texData ); }\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ImageLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tImageLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ImageLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' );\r\n\r\n\t\t\tfunction onImageLoad() {\r\n\r\n\t\t\t\timage.removeEventListener( 'load', onImageLoad, false );\r\n\t\t\t\timage.removeEventListener( 'error', onImageError, false );\r\n\r\n\t\t\t\tCache.add( url, this );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( this ); }\r\n\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction onImageError( event ) {\r\n\r\n\t\t\t\timage.removeEventListener( 'load', onImageLoad, false );\r\n\t\t\t\timage.removeEventListener( 'error', onImageError, false );\r\n\r\n\t\t\t\tif ( onError ) { onError( event ); }\r\n\r\n\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\timage.addEventListener( 'load', onImageLoad, false );\r\n\t\t\timage.addEventListener( 'error', onImageError, false );\r\n\r\n\t\t\tif ( url.substr( 0, 5 ) !== 'data:' ) {\r\n\r\n\t\t\t\tif ( this.crossOrigin !== undefined ) { image.crossOrigin = this.crossOrigin; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\timage.src = url;\r\n\r\n\t\t\treturn image;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction CubeTextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: CubeTextureLoader,\r\n\r\n\t\tload: function ( urls, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar texture = new CubeTexture();\r\n\r\n\t\t\tvar loader = new ImageLoader( this.manager );\r\n\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\t\t\tloader.setPath( this.path );\r\n\r\n\t\t\tvar loaded = 0;\r\n\r\n\t\t\tfunction loadTexture( i ) {\r\n\r\n\t\t\t\tloader.load( urls[ i ], function ( image ) {\r\n\r\n\t\t\t\t\ttexture.images[ i ] = image;\r\n\r\n\t\t\t\t\tloaded ++;\r\n\r\n\t\t\t\t\tif ( loaded === 6 ) {\r\n\r\n\t\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\t\tif ( onLoad ) { onLoad( texture ); }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}, undefined, onError );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i < urls.length; ++ i ) {\r\n\r\n\t\t\t\tloadTexture( i );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction TextureLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: TextureLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar texture = new Texture();\r\n\r\n\t\t\tvar loader = new ImageLoader( this.manager );\r\n\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\t\t\tloader.setPath( this.path );\r\n\r\n\t\t\tloader.load( url, function ( image ) {\r\n\r\n\t\t\t\ttexture.image = image;\r\n\r\n\t\t\t\t// JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB.\r\n\t\t\t\tvar isJPEG = url.search( /\\.jpe?g($|\\?)/i ) > 0 || url.search( /^data\\:image\\/jpeg/ ) === 0;\r\n\r\n\t\t\t\ttexture.format = isJPEG ? RGBFormat : RGBAFormat;\r\n\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) {\r\n\r\n\t\t\t\t\tonLoad( texture );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Extensible curve object\r\n\t *\r\n\t * Some common of curve methods:\r\n\t * .getPoint( t, optionalTarget ), .getTangent( t )\r\n\t * .getPointAt( u, optionalTarget ), .getTangentAt( u )\r\n\t * .getPoints(), .getSpacedPoints()\r\n\t * .getLength()\r\n\t * .updateArcLengths()\r\n\t *\r\n\t * This following curves inherit from THREE.Curve:\r\n\t *\r\n\t * -- 2D curves --\r\n\t * THREE.ArcCurve\r\n\t * THREE.CubicBezierCurve\r\n\t * THREE.EllipseCurve\r\n\t * THREE.LineCurve\r\n\t * THREE.QuadraticBezierCurve\r\n\t * THREE.SplineCurve\r\n\t *\r\n\t * -- 3D curves --\r\n\t * THREE.CatmullRomCurve3\r\n\t * THREE.CubicBezierCurve3\r\n\t * THREE.LineCurve3\r\n\t * THREE.QuadraticBezierCurve3\r\n\t *\r\n\t * A series of curves can be represented as a THREE.CurvePath.\r\n\t *\r\n\t **/\r\n\r\n\t/**************************************************************\r\n\t *\tAbstract Curve base class\r\n\t **************************************************************/\r\n\r\n\tfunction Curve() {\r\n\r\n\t\tthis.type = 'Curve';\r\n\r\n\t\tthis.arcLengthDivisions = 200;\r\n\r\n\t}\r\n\r\n\tObject.assign( Curve.prototype, {\r\n\r\n\t\t// Virtual base class method to overwrite and implement in subclasses\r\n\t\t//\t- t [0 .. 1]\r\n\r\n\t\tgetPoint: function ( /* t, optionalTarget */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .getPoint() not implemented.' );\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\t// Get point at relative position in curve according to arc length\r\n\t\t// - u [0 .. 1]\r\n\r\n\t\tgetPointAt: function ( u, optionalTarget ) {\r\n\r\n\t\t\tvar t = this.getUtoTmapping( u );\r\n\t\t\treturn this.getPoint( t, optionalTarget );\r\n\r\n\t\t},\r\n\r\n\t\t// Get sequence of points using getPoint( t )\r\n\r\n\t\tgetPoints: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = 5; }\r\n\r\n\t\t\tvar points = [];\r\n\r\n\t\t\tfor ( var d = 0; d <= divisions; d ++ ) {\r\n\r\n\t\t\t\tpoints.push( this.getPoint( d / divisions ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\t// Get sequence of points using getPointAt( u )\r\n\r\n\t\tgetSpacedPoints: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = 5; }\r\n\r\n\t\t\tvar points = [];\r\n\r\n\t\t\tfor ( var d = 0; d <= divisions; d ++ ) {\r\n\r\n\t\t\t\tpoints.push( this.getPointAt( d / divisions ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\t// Get total curve arc length\r\n\r\n\t\tgetLength: function () {\r\n\r\n\t\t\tvar lengths = this.getLengths();\r\n\t\t\treturn lengths[ lengths.length - 1 ];\r\n\r\n\t\t},\r\n\r\n\t\t// Get list of cumulative segment lengths\r\n\r\n\t\tgetLengths: function ( divisions ) {\r\n\r\n\t\t\tif ( divisions === undefined ) { divisions = this.arcLengthDivisions; }\r\n\r\n\t\t\tif ( this.cacheArcLengths &&\r\n\t\t\t\t( this.cacheArcLengths.length === divisions + 1 ) &&\r\n\t\t\t\t! this.needsUpdate ) {\r\n\r\n\t\t\t\treturn this.cacheArcLengths;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.needsUpdate = false;\r\n\r\n\t\t\tvar cache = [];\r\n\t\t\tvar current, last = this.getPoint( 0 );\r\n\t\t\tvar p, sum = 0;\r\n\r\n\t\t\tcache.push( 0 );\r\n\r\n\t\t\tfor ( p = 1; p <= divisions; p ++ ) {\r\n\r\n\t\t\t\tcurrent = this.getPoint( p / divisions );\r\n\t\t\t\tsum += current.distanceTo( last );\r\n\t\t\t\tcache.push( sum );\r\n\t\t\t\tlast = current;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cacheArcLengths = cache;\r\n\r\n\t\t\treturn cache; // { sums: cache, sum: sum }; Sum is in the last element.\r\n\r\n\t\t},\r\n\r\n\t\tupdateArcLengths: function () {\r\n\r\n\t\t\tthis.needsUpdate = true;\r\n\t\t\tthis.getLengths();\r\n\r\n\t\t},\r\n\r\n\t\t// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant\r\n\r\n\t\tgetUtoTmapping: function ( u, distance ) {\r\n\r\n\t\t\tvar arcLengths = this.getLengths();\r\n\r\n\t\t\tvar i = 0, il = arcLengths.length;\r\n\r\n\t\t\tvar targetArcLength; // The targeted u distance value to get\r\n\r\n\t\t\tif ( distance ) {\r\n\r\n\t\t\t\ttargetArcLength = distance;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\ttargetArcLength = u * arcLengths[ il - 1 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// binary search for the index with largest value smaller than target u distance\r\n\r\n\t\t\tvar low = 0, high = il - 1, comparison;\r\n\r\n\t\t\twhile ( low <= high ) {\r\n\r\n\t\t\t\ti = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats\r\n\r\n\t\t\t\tcomparison = arcLengths[ i ] - targetArcLength;\r\n\r\n\t\t\t\tif ( comparison < 0 ) {\r\n\r\n\t\t\t\t\tlow = i + 1;\r\n\r\n\t\t\t\t} else if ( comparison > 0 ) {\r\n\r\n\t\t\t\t\thigh = i - 1;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\thigh = i;\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t// DONE\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\ti = high;\r\n\r\n\t\t\tif ( arcLengths[ i ] === targetArcLength ) {\r\n\r\n\t\t\t\treturn i / ( il - 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// we could get finer grain at lengths, or use simple interpolation between two points\r\n\r\n\t\t\tvar lengthBefore = arcLengths[ i ];\r\n\t\t\tvar lengthAfter = arcLengths[ i + 1 ];\r\n\r\n\t\t\tvar segmentLength = lengthAfter - lengthBefore;\r\n\r\n\t\t\t// determine where we are between the 'before' and 'after' points\r\n\r\n\t\t\tvar segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;\r\n\r\n\t\t\t// add that fractional amount to t\r\n\r\n\t\t\tvar t = ( i + segmentFraction ) / ( il - 1 );\r\n\r\n\t\t\treturn t;\r\n\r\n\t\t},\r\n\r\n\t\t// Returns a unit vector tangent at t\r\n\t\t// In case any sub curve does not implement its tangent derivation,\r\n\t\t// 2 points a small delta apart will be used to find its gradient\r\n\t\t// which seems to give a reasonable approximation\r\n\r\n\t\tgetTangent: function ( t ) {\r\n\r\n\t\t\tvar delta = 0.0001;\r\n\t\t\tvar t1 = t - delta;\r\n\t\t\tvar t2 = t + delta;\r\n\r\n\t\t\t// Capping in case of danger\r\n\r\n\t\t\tif ( t1 < 0 ) { t1 = 0; }\r\n\t\t\tif ( t2 > 1 ) { t2 = 1; }\r\n\r\n\t\t\tvar pt1 = this.getPoint( t1 );\r\n\t\t\tvar pt2 = this.getPoint( t2 );\r\n\r\n\t\t\tvar vec = pt2.clone().sub( pt1 );\r\n\t\t\treturn vec.normalize();\r\n\r\n\t\t},\r\n\r\n\t\tgetTangentAt: function ( u ) {\r\n\r\n\t\t\tvar t = this.getUtoTmapping( u );\r\n\t\t\treturn this.getTangent( t );\r\n\r\n\t\t},\r\n\r\n\t\tcomputeFrenetFrames: function ( segments, closed ) {\r\n\r\n\t\t\t// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf\r\n\r\n\t\t\tvar normal = new Vector3();\r\n\r\n\t\t\tvar tangents = [];\r\n\t\t\tvar normals = [];\r\n\t\t\tvar binormals = [];\r\n\r\n\t\t\tvar vec = new Vector3();\r\n\t\t\tvar mat = new Matrix4();\r\n\r\n\t\t\tvar i, u, theta;\r\n\r\n\t\t\t// compute the tangent vectors for each segment on the curve\r\n\r\n\t\t\tfor ( i = 0; i <= segments; i ++ ) {\r\n\r\n\t\t\t\tu = i / segments;\r\n\r\n\t\t\t\ttangents[ i ] = this.getTangentAt( u );\r\n\t\t\t\ttangents[ i ].normalize();\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// select an initial normal vector perpendicular to the first tangent vector,\r\n\t\t\t// and in the direction of the minimum tangent xyz component\r\n\r\n\t\t\tnormals[ 0 ] = new Vector3();\r\n\t\t\tbinormals[ 0 ] = new Vector3();\r\n\t\t\tvar min = Number.MAX_VALUE;\r\n\t\t\tvar tx = Math.abs( tangents[ 0 ].x );\r\n\t\t\tvar ty = Math.abs( tangents[ 0 ].y );\r\n\t\t\tvar tz = Math.abs( tangents[ 0 ].z );\r\n\r\n\t\t\tif ( tx <= min ) {\r\n\r\n\t\t\t\tmin = tx;\r\n\t\t\t\tnormal.set( 1, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( ty <= min ) {\r\n\r\n\t\t\t\tmin = ty;\r\n\t\t\t\tnormal.set( 0, 1, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( tz <= min ) {\r\n\r\n\t\t\t\tnormal.set( 0, 0, 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvec.crossVectors( tangents[ 0 ], normal ).normalize();\r\n\r\n\t\t\tnormals[ 0 ].crossVectors( tangents[ 0 ], vec );\r\n\t\t\tbinormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );\r\n\r\n\r\n\t\t\t// compute the slowly-varying normal and binormal vectors for each segment on the curve\r\n\r\n\t\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\t\tnormals[ i ] = normals[ i - 1 ].clone();\r\n\r\n\t\t\t\tbinormals[ i ] = binormals[ i - 1 ].clone();\r\n\r\n\t\t\t\tvec.crossVectors( tangents[ i - 1 ], tangents[ i ] );\r\n\r\n\t\t\t\tif ( vec.length() > Number.EPSILON ) {\r\n\r\n\t\t\t\t\tvec.normalize();\r\n\r\n\t\t\t\t\ttheta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors\r\n\r\n\t\t\t\t\tnormals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbinormals[ i ].crossVectors( tangents[ i ], normals[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same\r\n\r\n\t\t\tif ( closed === true ) {\r\n\r\n\t\t\t\ttheta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );\r\n\t\t\t\ttheta /= segments;\r\n\r\n\t\t\t\tif ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {\r\n\r\n\t\t\t\t\ttheta = - theta;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( i = 1; i <= segments; i ++ ) {\r\n\r\n\t\t\t\t\t// twist a little...\r\n\t\t\t\t\tnormals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );\r\n\t\t\t\t\tbinormals[ i ].crossVectors( tangents[ i ], normals[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn {\r\n\t\t\t\ttangents: tangents,\r\n\t\t\t\tnormals: normals,\r\n\t\t\t\tbinormals: binormals\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.arcLengthDivisions = source.arcLengthDivisions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = {\r\n\t\t\t\tmetadata: {\r\n\t\t\t\t\tversion: 4.5,\r\n\t\t\t\t\ttype: 'Curve',\r\n\t\t\t\t\tgenerator: 'Curve.toJSON'\r\n\t\t\t\t}\r\n\t\t\t};\r\n\r\n\t\t\tdata.arcLengthDivisions = this.arcLengthDivisions;\r\n\t\t\tdata.type = this.type;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tthis.arcLengthDivisions = json.arcLengthDivisions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tfunction EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'EllipseCurve';\r\n\r\n\t\tthis.aX = aX || 0;\r\n\t\tthis.aY = aY || 0;\r\n\r\n\t\tthis.xRadius = xRadius || 1;\r\n\t\tthis.yRadius = yRadius || 1;\r\n\r\n\t\tthis.aStartAngle = aStartAngle || 0;\r\n\t\tthis.aEndAngle = aEndAngle || 2 * Math.PI;\r\n\r\n\t\tthis.aClockwise = aClockwise || false;\r\n\r\n\t\tthis.aRotation = aRotation || 0;\r\n\r\n\t}\r\n\r\n\tEllipseCurve.prototype = Object.create( Curve.prototype );\r\n\tEllipseCurve.prototype.constructor = EllipseCurve;\r\n\r\n\tEllipseCurve.prototype.isEllipseCurve = true;\r\n\r\n\tEllipseCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar twoPi = Math.PI * 2;\r\n\t\tvar deltaAngle = this.aEndAngle - this.aStartAngle;\r\n\t\tvar samePoints = Math.abs( deltaAngle ) < Number.EPSILON;\r\n\r\n\t\t// ensures that deltaAngle is 0 .. 2 PI\r\n\t\twhile ( deltaAngle < 0 ) { deltaAngle += twoPi; }\r\n\t\twhile ( deltaAngle > twoPi ) { deltaAngle -= twoPi; }\r\n\r\n\t\tif ( deltaAngle < Number.EPSILON ) {\r\n\r\n\t\t\tif ( samePoints ) {\r\n\r\n\t\t\t\tdeltaAngle = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdeltaAngle = twoPi;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.aClockwise === true && ! samePoints ) {\r\n\r\n\t\t\tif ( deltaAngle === twoPi ) {\r\n\r\n\t\t\t\tdeltaAngle = - twoPi;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tdeltaAngle = deltaAngle - twoPi;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar angle = this.aStartAngle + t * deltaAngle;\r\n\t\tvar x = this.aX + this.xRadius * Math.cos( angle );\r\n\t\tvar y = this.aY + this.yRadius * Math.sin( angle );\r\n\r\n\t\tif ( this.aRotation !== 0 ) {\r\n\r\n\t\t\tvar cos = Math.cos( this.aRotation );\r\n\t\t\tvar sin = Math.sin( this.aRotation );\r\n\r\n\t\t\tvar tx = x - this.aX;\r\n\t\t\tvar ty = y - this.aY;\r\n\r\n\t\t\t// Rotate the point about the center of the ellipse.\r\n\t\t\tx = tx * cos - ty * sin + this.aX;\r\n\t\t\ty = tx * sin + ty * cos + this.aY;\r\n\r\n\t\t}\r\n\r\n\t\treturn point.set( x, y );\r\n\r\n\t};\r\n\r\n\tEllipseCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.aX = source.aX;\r\n\t\tthis.aY = source.aY;\r\n\r\n\t\tthis.xRadius = source.xRadius;\r\n\t\tthis.yRadius = source.yRadius;\r\n\r\n\t\tthis.aStartAngle = source.aStartAngle;\r\n\t\tthis.aEndAngle = source.aEndAngle;\r\n\r\n\t\tthis.aClockwise = source.aClockwise;\r\n\r\n\t\tthis.aRotation = source.aRotation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\r\n\tEllipseCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.aX = this.aX;\r\n\t\tdata.aY = this.aY;\r\n\r\n\t\tdata.xRadius = this.xRadius;\r\n\t\tdata.yRadius = this.yRadius;\r\n\r\n\t\tdata.aStartAngle = this.aStartAngle;\r\n\t\tdata.aEndAngle = this.aEndAngle;\r\n\r\n\t\tdata.aClockwise = this.aClockwise;\r\n\r\n\t\tdata.aRotation = this.aRotation;\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tEllipseCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.aX = json.aX;\r\n\t\tthis.aY = json.aY;\r\n\r\n\t\tthis.xRadius = json.xRadius;\r\n\t\tthis.yRadius = json.yRadius;\r\n\r\n\t\tthis.aStartAngle = json.aStartAngle;\r\n\t\tthis.aEndAngle = json.aEndAngle;\r\n\r\n\t\tthis.aClockwise = json.aClockwise;\r\n\r\n\t\tthis.aRotation = json.aRotation;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\tEllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\tthis.type = 'ArcCurve';\r\n\r\n\t}\r\n\r\n\tArcCurve.prototype = Object.create( EllipseCurve.prototype );\r\n\tArcCurve.prototype.constructor = ArcCurve;\r\n\r\n\tArcCurve.prototype.isArcCurve = true;\n\n\t/**\r\n\t * @author zz85 https://github.com/zz85\r\n\t *\r\n\t * Centripetal CatmullRom Curve - which is useful for avoiding\r\n\t * cusps and self-intersections in non-uniform catmull rom curves.\r\n\t * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf\r\n\t *\r\n\t * curve.type accepts centripetal(default), chordal and catmullrom\r\n\t * curve.tension is used for catmullrom which defaults to 0.5\r\n\t */\r\n\r\n\r\n\t/*\r\n\tBased on an optimized c++ solution in\r\n\t - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/\r\n\t - http://ideone.com/NoEbVM\r\n\r\n\tThis CubicPoly class could be used for reusing some variables and calculations,\r\n\tbut for three.js curve use, it could be possible inlined and flatten into a single function call\r\n\twhich can be placed in CurveUtils.\r\n\t*/\r\n\r\n\tfunction CubicPoly() {\r\n\r\n\t\tvar c0 = 0, c1 = 0, c2 = 0, c3 = 0;\r\n\r\n\t\t/*\r\n\t\t * Compute coefficients for a cubic polynomial\r\n\t\t * p(s) = c0 + c1*s + c2*s^2 + c3*s^3\r\n\t\t * such that\r\n\t\t * p(0) = x0, p(1) = x1\r\n\t\t * and\r\n\t\t * p'(0) = t0, p'(1) = t1.\r\n\t\t */\r\n\t\tfunction init( x0, x1, t0, t1 ) {\r\n\r\n\t\t\tc0 = x0;\r\n\t\t\tc1 = t0;\r\n\t\t\tc2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;\r\n\t\t\tc3 = 2 * x0 - 2 * x1 + t0 + t1;\r\n\r\n\t\t}\r\n\r\n\t\treturn {\r\n\r\n\t\t\tinitCatmullRom: function ( x0, x1, x2, x3, tension ) {\r\n\r\n\t\t\t\tinit( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );\r\n\r\n\t\t\t},\r\n\r\n\t\t\tinitNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {\r\n\r\n\t\t\t\t// compute tangents when parameterized in [t1,t2]\r\n\t\t\t\tvar t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;\r\n\t\t\t\tvar t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;\r\n\r\n\t\t\t\t// rescale tangents for parametrization in [0,1]\r\n\t\t\t\tt1 *= dt1;\r\n\t\t\t\tt2 *= dt1;\r\n\r\n\t\t\t\tinit( x1, x2, t1, t2 );\r\n\r\n\t\t\t},\r\n\r\n\t\t\tcalc: function ( t ) {\r\n\r\n\t\t\t\tvar t2 = t * t;\r\n\t\t\t\tvar t3 = t2 * t;\r\n\t\t\t\treturn c0 + c1 * t + c2 * t2 + c3 * t3;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tvar tmp = new Vector3();\r\n\tvar px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly();\r\n\r\n\tfunction CatmullRomCurve3( points, closed, curveType, tension ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CatmullRomCurve3';\r\n\r\n\t\tthis.points = points || [];\r\n\t\tthis.closed = closed || false;\r\n\t\tthis.curveType = curveType || 'centripetal';\r\n\t\tthis.tension = tension || 0.5;\r\n\r\n\t}\r\n\r\n\tCatmullRomCurve3.prototype = Object.create( Curve.prototype );\r\n\tCatmullRomCurve3.prototype.constructor = CatmullRomCurve3;\r\n\r\n\tCatmullRomCurve3.prototype.isCatmullRomCurve3 = true;\r\n\r\n\tCatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar points = this.points;\r\n\t\tvar l = points.length;\r\n\r\n\t\tvar p = ( l - ( this.closed ? 0 : 1 ) ) * t;\r\n\t\tvar intPoint = Math.floor( p );\r\n\t\tvar weight = p - intPoint;\r\n\r\n\t\tif ( this.closed ) {\r\n\r\n\t\t\tintPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l;\r\n\r\n\t\t} else if ( weight === 0 && intPoint === l - 1 ) {\r\n\r\n\t\t\tintPoint = l - 2;\r\n\t\t\tweight = 1;\r\n\r\n\t\t}\r\n\r\n\t\tvar p0, p1, p2, p3; // 4 points\r\n\r\n\t\tif ( this.closed || intPoint > 0 ) {\r\n\r\n\t\t\tp0 = points[ ( intPoint - 1 ) % l ];\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// extrapolate first point\r\n\t\t\ttmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );\r\n\t\t\tp0 = tmp;\r\n\r\n\t\t}\r\n\r\n\t\tp1 = points[ intPoint % l ];\r\n\t\tp2 = points[ ( intPoint + 1 ) % l ];\r\n\r\n\t\tif ( this.closed || intPoint + 2 < l ) {\r\n\r\n\t\t\tp3 = points[ ( intPoint + 2 ) % l ];\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// extrapolate last point\r\n\t\t\ttmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );\r\n\t\t\tp3 = tmp;\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) {\r\n\r\n\t\t\t// init Centripetal / Chordal Catmull-Rom\r\n\t\t\tvar pow = this.curveType === 'chordal' ? 0.5 : 0.25;\r\n\t\t\tvar dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );\r\n\t\t\tvar dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );\r\n\t\t\tvar dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );\r\n\r\n\t\t\t// safety check for repeated points\r\n\t\t\tif ( dt1 < 1e-4 ) { dt1 = 1.0; }\r\n\t\t\tif ( dt0 < 1e-4 ) { dt0 = dt1; }\r\n\t\t\tif ( dt2 < 1e-4 ) { dt2 = dt1; }\r\n\r\n\t\t\tpx.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );\r\n\t\t\tpy.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );\r\n\t\t\tpz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );\r\n\r\n\t\t} else if ( this.curveType === 'catmullrom' ) {\r\n\r\n\t\t\tpx.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension );\r\n\t\t\tpy.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension );\r\n\t\t\tpz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension );\r\n\r\n\t\t}\r\n\r\n\t\tpoint.set(\r\n\t\t\tpx.calc( weight ),\r\n\t\t\tpy.calc( weight ),\r\n\t\t\tpz.calc( weight )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = source.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = source.points[ i ];\r\n\r\n\t\t\tthis.points.push( point.clone() );\r\n\r\n\t\t}\r\n\r\n\t\tthis.closed = source.closed;\r\n\t\tthis.curveType = source.curveType;\r\n\t\tthis.tension = source.tension;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.points = [];\r\n\r\n\t\tfor ( var i = 0, l = this.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = this.points[ i ];\r\n\t\t\tdata.points.push( point.toArray() );\r\n\r\n\t\t}\r\n\r\n\t\tdata.closed = this.closed;\r\n\t\tdata.curveType = this.curveType;\r\n\t\tdata.tension = this.tension;\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCatmullRomCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = json.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = json.points[ i ];\r\n\t\t\tthis.points.push( new Vector3().fromArray( point ) );\r\n\r\n\t\t}\r\n\r\n\t\tthis.closed = json.closed;\r\n\t\tthis.curveType = json.curveType;\r\n\t\tthis.tension = json.tension;\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t * Bezier Curves formulas obtained from\r\n\t * http://en.wikipedia.org/wiki/Bézier_curve\r\n\t */\r\n\r\n\tfunction CatmullRom( t, p0, p1, p2, p3 ) {\r\n\r\n\t\tvar v0 = ( p2 - p0 ) * 0.5;\r\n\t\tvar v1 = ( p3 - p1 ) * 0.5;\r\n\t\tvar t2 = t * t;\r\n\t\tvar t3 = t * t2;\r\n\t\treturn ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction QuadraticBezierP0( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn k * k * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezierP1( t, p ) {\r\n\r\n\t\treturn 2 * ( 1 - t ) * t * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezierP2( t, p ) {\r\n\r\n\t\treturn t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction QuadraticBezier( t, p0, p1, p2 ) {\r\n\r\n\t\treturn QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) +\r\n\t\t\tQuadraticBezierP2( t, p2 );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction CubicBezierP0( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn k * k * k * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP1( t, p ) {\r\n\r\n\t\tvar k = 1 - t;\r\n\t\treturn 3 * k * k * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP2( t, p ) {\r\n\r\n\t\treturn 3 * ( 1 - t ) * t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezierP3( t, p ) {\r\n\r\n\t\treturn t * t * t * p;\r\n\r\n\t}\r\n\r\n\tfunction CubicBezier( t, p0, p1, p2, p3 ) {\r\n\r\n\t\treturn CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) +\r\n\t\t\tCubicBezierP3( t, p3 );\r\n\r\n\t}\n\n\tfunction CubicBezierCurve( v0, v1, v2, v3 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CubicBezierCurve';\r\n\r\n\t\tthis.v0 = v0 || new Vector2();\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\t\tthis.v3 = v3 || new Vector2();\r\n\r\n\t}\r\n\r\n\tCubicBezierCurve.prototype = Object.create( Curve.prototype );\r\n\tCubicBezierCurve.prototype.constructor = CubicBezierCurve;\r\n\r\n\tCubicBezierCurve.prototype.isCubicBezierCurve = true;\r\n\r\n\tCubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;\r\n\r\n\t\tpoint.set(\r\n\t\t\tCubicBezier( t, v0.x, v1.x, v2.x, v3.x ),\r\n\t\t\tCubicBezier( t, v0.y, v1.y, v2.y, v3.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\t\tthis.v3.copy( source.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\t\tdata.v3 = this.v3.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\t\tthis.v3.fromArray( json.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction CubicBezierCurve3( v0, v1, v2, v3 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CubicBezierCurve3';\r\n\r\n\t\tthis.v0 = v0 || new Vector3();\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\t\tthis.v3 = v3 || new Vector3();\r\n\r\n\t}\r\n\r\n\tCubicBezierCurve3.prototype = Object.create( Curve.prototype );\r\n\tCubicBezierCurve3.prototype.constructor = CubicBezierCurve3;\r\n\r\n\tCubicBezierCurve3.prototype.isCubicBezierCurve3 = true;\r\n\r\n\tCubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3;\r\n\r\n\t\tpoint.set(\r\n\t\t\tCubicBezier( t, v0.x, v1.x, v2.x, v3.x ),\r\n\t\t\tCubicBezier( t, v0.y, v1.y, v2.y, v3.y ),\r\n\t\t\tCubicBezier( t, v0.z, v1.z, v2.z, v3.z )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\t\tthis.v3.copy( source.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\t\tdata.v3 = this.v3.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tCubicBezierCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\t\tthis.v3.fromArray( json.v3 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction LineCurve( v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'LineCurve';\r\n\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\r\n\t}\r\n\r\n\tLineCurve.prototype = Object.create( Curve.prototype );\r\n\tLineCurve.prototype.constructor = LineCurve;\r\n\r\n\tLineCurve.prototype.isLineCurve = true;\r\n\r\n\tLineCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tif ( t === 1 ) {\r\n\r\n\t\t\tpoint.copy( this.v2 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tpoint.copy( this.v2 ).sub( this.v1 );\r\n\t\t\tpoint.multiplyScalar( t ).add( this.v1 );\r\n\r\n\t\t}\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\t// Line curve is linear, so we can overwrite default getPointAt\r\n\r\n\tLineCurve.prototype.getPointAt = function ( u, optionalTarget ) {\r\n\r\n\t\treturn this.getPoint( u, optionalTarget );\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.getTangent = function ( /* t */ ) {\r\n\r\n\t\tvar tangent = this.v2.clone().sub( this.v1 );\r\n\r\n\t\treturn tangent.normalize();\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tLineCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction LineCurve3( v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'LineCurve3';\r\n\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\r\n\t}\r\n\r\n\tLineCurve3.prototype = Object.create( Curve.prototype );\r\n\tLineCurve3.prototype.constructor = LineCurve3;\r\n\r\n\tLineCurve3.prototype.isLineCurve3 = true;\r\n\r\n\tLineCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tif ( t === 1 ) {\r\n\r\n\t\t\tpoint.copy( this.v2 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tpoint.copy( this.v2 ).sub( this.v1 );\r\n\t\t\tpoint.multiplyScalar( t ).add( this.v1 );\r\n\r\n\t\t}\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\t// Line curve is linear, so we can overwrite default getPointAt\r\n\r\n\tLineCurve3.prototype.getPointAt = function ( u, optionalTarget ) {\r\n\r\n\t\treturn this.getPoint( u, optionalTarget );\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tLineCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction QuadraticBezierCurve( v0, v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'QuadraticBezierCurve';\r\n\r\n\t\tthis.v0 = v0 || new Vector2();\r\n\t\tthis.v1 = v1 || new Vector2();\r\n\t\tthis.v2 = v2 || new Vector2();\r\n\r\n\t}\r\n\r\n\tQuadraticBezierCurve.prototype = Object.create( Curve.prototype );\r\n\tQuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve;\r\n\r\n\tQuadraticBezierCurve.prototype.isQuadraticBezierCurve = true;\r\n\r\n\tQuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2;\r\n\r\n\t\tpoint.set(\r\n\t\t\tQuadraticBezier( t, v0.x, v1.x, v2.x ),\r\n\t\t\tQuadraticBezier( t, v0.y, v1.y, v2.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction QuadraticBezierCurve3( v0, v1, v2 ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'QuadraticBezierCurve3';\r\n\r\n\t\tthis.v0 = v0 || new Vector3();\r\n\t\tthis.v1 = v1 || new Vector3();\r\n\t\tthis.v2 = v2 || new Vector3();\r\n\r\n\t}\r\n\r\n\tQuadraticBezierCurve3.prototype = Object.create( Curve.prototype );\r\n\tQuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3;\r\n\r\n\tQuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true;\r\n\r\n\tQuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector3();\r\n\r\n\t\tvar v0 = this.v0, v1 = this.v1, v2 = this.v2;\r\n\r\n\t\tpoint.set(\r\n\t\t\tQuadraticBezier( t, v0.x, v1.x, v2.x ),\r\n\t\t\tQuadraticBezier( t, v0.y, v1.y, v2.y ),\r\n\t\t\tQuadraticBezier( t, v0.z, v1.z, v2.z )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.v0.copy( source.v0 );\r\n\t\tthis.v1.copy( source.v1 );\r\n\t\tthis.v2.copy( source.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.v0 = this.v0.toArray();\r\n\t\tdata.v1 = this.v1.toArray();\r\n\t\tdata.v2 = this.v2.toArray();\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tQuadraticBezierCurve3.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.v0.fromArray( json.v0 );\r\n\t\tthis.v1.fromArray( json.v1 );\r\n\t\tthis.v2.fromArray( json.v2 );\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\tfunction SplineCurve( points /* array of Vector2 */ ) {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'SplineCurve';\r\n\r\n\t\tthis.points = points || [];\r\n\r\n\t}\r\n\r\n\tSplineCurve.prototype = Object.create( Curve.prototype );\r\n\tSplineCurve.prototype.constructor = SplineCurve;\r\n\r\n\tSplineCurve.prototype.isSplineCurve = true;\r\n\r\n\tSplineCurve.prototype.getPoint = function ( t, optionalTarget ) {\r\n\r\n\t\tvar point = optionalTarget || new Vector2();\r\n\r\n\t\tvar points = this.points;\r\n\t\tvar p = ( points.length - 1 ) * t;\r\n\r\n\t\tvar intPoint = Math.floor( p );\r\n\t\tvar weight = p - intPoint;\r\n\r\n\t\tvar p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];\r\n\t\tvar p1 = points[ intPoint ];\r\n\t\tvar p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];\r\n\t\tvar p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];\r\n\r\n\t\tpoint.set(\r\n\t\t\tCatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),\r\n\t\t\tCatmullRom( weight, p0.y, p1.y, p2.y, p3.y )\r\n\t\t);\r\n\r\n\t\treturn point;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.copy = function ( source ) {\r\n\r\n\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = source.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = source.points[ i ];\r\n\r\n\t\t\tthis.points.push( point.clone() );\r\n\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.toJSON = function () {\r\n\r\n\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\tdata.points = [];\r\n\r\n\t\tfor ( var i = 0, l = this.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = this.points[ i ];\r\n\t\t\tdata.points.push( point.toArray() );\r\n\r\n\t\t}\r\n\r\n\t\treturn data;\r\n\r\n\t};\r\n\r\n\tSplineCurve.prototype.fromJSON = function ( json ) {\r\n\r\n\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\tthis.points = [];\r\n\r\n\t\tfor ( var i = 0, l = json.points.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar point = json.points[ i ];\r\n\t\t\tthis.points.push( new Vector2().fromArray( point ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn this;\r\n\r\n\t};\n\n\n\n\tvar Curves = /*#__PURE__*/Object.freeze({\n\t\t__proto__: null,\n\t\tArcCurve: ArcCurve,\n\t\tCatmullRomCurve3: CatmullRomCurve3,\n\t\tCubicBezierCurve: CubicBezierCurve,\n\t\tCubicBezierCurve3: CubicBezierCurve3,\n\t\tEllipseCurve: EllipseCurve,\n\t\tLineCurve: LineCurve,\n\t\tLineCurve3: LineCurve3,\n\t\tQuadraticBezierCurve: QuadraticBezierCurve,\n\t\tQuadraticBezierCurve3: QuadraticBezierCurve3,\n\t\tSplineCurve: SplineCurve\n\t});\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t *\r\n\t **/\r\n\r\n\t/**************************************************************\r\n\t *\tCurved Path - a curve path is simply a array of connected\r\n\t * curves, but retains the api of a curve\r\n\t **************************************************************/\r\n\r\n\tfunction CurvePath() {\r\n\r\n\t\tCurve.call( this );\r\n\r\n\t\tthis.type = 'CurvePath';\r\n\r\n\t\tthis.curves = [];\r\n\t\tthis.autoClose = false; // Automatically closes the path\r\n\r\n\t}\r\n\r\n\tCurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {\r\n\r\n\t\tconstructor: CurvePath,\r\n\r\n\t\tadd: function ( curve ) {\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t},\r\n\r\n\t\tclosePath: function () {\r\n\r\n\t\t\t// Add a line curve if start and end of lines are not connected\r\n\t\t\tvar startPoint = this.curves[ 0 ].getPoint( 0 );\r\n\t\t\tvar endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );\r\n\r\n\t\t\tif ( ! startPoint.equals( endPoint ) ) {\r\n\r\n\t\t\t\tthis.curves.push( new LineCurve( endPoint, startPoint ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// To get accurate point with reference to\r\n\t\t// entire path distance at time t,\r\n\t\t// following has to be done:\r\n\r\n\t\t// 1. Length of each sub path have to be known\r\n\t\t// 2. Locate and identify type of curve\r\n\t\t// 3. Get t for the curve\r\n\t\t// 4. Return curve.getPointAt(t')\r\n\r\n\t\tgetPoint: function ( t ) {\r\n\r\n\t\t\tvar d = t * this.getLength();\r\n\t\t\tvar curveLengths = this.getCurveLengths();\r\n\t\t\tvar i = 0;\r\n\r\n\t\t\t// To think about boundaries points.\r\n\r\n\t\t\twhile ( i < curveLengths.length ) {\r\n\r\n\t\t\t\tif ( curveLengths[ i ] >= d ) {\r\n\r\n\t\t\t\t\tvar diff = curveLengths[ i ] - d;\r\n\t\t\t\t\tvar curve = this.curves[ i ];\r\n\r\n\t\t\t\t\tvar segmentLength = curve.getLength();\r\n\t\t\t\t\tvar u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;\r\n\r\n\t\t\t\t\treturn curve.getPointAt( u );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\ti ++;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t\t// loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {\r\n\r\n\t\t\t\tpoints.push( points[ 0 ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn points;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tCurve.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = source.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = source.curves[ i ];\r\n\r\n\t\t\t\tthis.curves.push( curve.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.autoClose = source.autoClose;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = Curve.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.autoClose = this.autoClose;\r\n\t\t\tdata.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = this.curves[ i ];\r\n\t\t\t\tdata.curves.push( curve.toJSON() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tCurve.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.autoClose = json.autoClose;\r\n\t\t\tthis.curves = [];\r\n\r\n\t\t\tfor ( var i = 0, l = json.curves.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar curve = json.curves[ i ];\r\n\t\t\t\tthis.curves.push( new Curves[ curve.type ]().fromJSON( curve ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Creates free form 2d path using series of points, lines or curves.\r\n\t **/\r\n\r\n\tfunction Path( points ) {\r\n\r\n\t\tCurvePath.call( this );\r\n\r\n\t\tthis.type = 'Path';\r\n\r\n\t\tthis.currentPoint = new Vector2();\r\n\r\n\t\tif ( points ) {\r\n\r\n\t\t\tthis.setFromPoints( points );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tPath.prototype = Object.assign( Object.create( CurvePath.prototype ), {\r\n\r\n\t\tconstructor: Path,\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.moveTo( points[ 0 ].x, points[ 0 ].y );\r\n\r\n\t\t\tfor ( var i = 1, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tthis.lineTo( points[ i ].x, points[ i ].y );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmoveTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying?\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlineTo: function ( x, y ) {\r\n\r\n\t\t\tvar curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) );\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tquadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {\r\n\r\n\t\t\tvar curve = new QuadraticBezierCurve(\r\n\t\t\t\tthis.currentPoint.clone(),\r\n\t\t\t\tnew Vector2( aCPx, aCPy ),\r\n\t\t\t\tnew Vector2( aX, aY )\r\n\t\t\t);\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tbezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {\r\n\r\n\t\t\tvar curve = new CubicBezierCurve(\r\n\t\t\t\tthis.currentPoint.clone(),\r\n\t\t\t\tnew Vector2( aCP1x, aCP1y ),\r\n\t\t\t\tnew Vector2( aCP2x, aCP2y ),\r\n\t\t\t\tnew Vector2( aX, aY )\r\n\t\t\t);\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.set( aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsplineThru: function ( pts /*Array of Vector*/ ) {\r\n\r\n\t\t\tvar npts = [ this.currentPoint.clone() ].concat( pts );\r\n\r\n\t\t\tvar curve = new SplineCurve( npts );\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tthis.currentPoint.copy( pts[ pts.length - 1 ] );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\t\tvar x0 = this.currentPoint.x;\r\n\t\t\tvar y0 = this.currentPoint.y;\r\n\r\n\t\t\tthis.absarc( aX + x0, aY + y0, aRadius,\r\n\t\t\t\taStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tabsarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {\r\n\r\n\t\t\tthis.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\t\tvar x0 = this.currentPoint.x;\r\n\t\t\tvar y0 = this.currentPoint.y;\r\n\r\n\t\t\tthis.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tabsellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {\r\n\r\n\t\t\tvar curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );\r\n\r\n\t\t\tif ( this.curves.length > 0 ) {\r\n\r\n\t\t\t\t// if a previous curve is present, attempt to join\r\n\t\t\t\tvar firstPoint = curve.getPoint( 0 );\r\n\r\n\t\t\t\tif ( ! firstPoint.equals( this.currentPoint ) ) {\r\n\r\n\t\t\t\t\tthis.lineTo( firstPoint.x, firstPoint.y );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.curves.push( curve );\r\n\r\n\t\t\tvar lastPoint = curve.getPoint( 1 );\r\n\t\t\tthis.currentPoint.copy( lastPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tCurvePath.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.currentPoint.copy( source.currentPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = CurvePath.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.currentPoint = this.currentPoint.toArray();\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tCurvePath.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.currentPoint.fromArray( json.currentPoint );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * Defines a 2d shape plane using paths.\r\n\t **/\r\n\r\n\t// STEP 1 Create a path.\r\n\t// STEP 2 Turn path into shape.\r\n\t// STEP 3 ExtrudeGeometry takes in Shape/Shapes\r\n\t// STEP 3a - Extract points from each shape, turn to vertices\r\n\t// STEP 3b - Triangulate each shape, add faces.\r\n\r\n\tfunction Shape( points ) {\r\n\r\n\t\tPath.call( this, points );\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\tthis.type = 'Shape';\r\n\r\n\t\tthis.holes = [];\r\n\r\n\t}\r\n\r\n\tShape.prototype = Object.assign( Object.create( Path.prototype ), {\r\n\r\n\t\tconstructor: Shape,\r\n\r\n\t\tgetPointsHoles: function ( divisions ) {\r\n\r\n\t\t\tvar holesPts = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tholesPts[ i ] = this.holes[ i ].getPoints( divisions );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn holesPts;\r\n\r\n\t\t},\r\n\r\n\t\t// get points of shape and holes (keypoints based on segments parameter)\r\n\r\n\t\textractPoints: function ( divisions ) {\r\n\r\n\t\t\treturn {\r\n\r\n\t\t\t\tshape: this.getPoints( divisions ),\r\n\t\t\t\tholes: this.getPointsHoles( divisions )\r\n\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tPath.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = source.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = source.holes[ i ];\r\n\r\n\t\t\t\tthis.holes.push( hole.clone() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = Path.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.uuid = this.uuid;\r\n\t\t\tdata.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = this.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = this.holes[ i ];\r\n\t\t\t\tdata.holes.push( hole.toJSON() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t},\r\n\r\n\t\tfromJSON: function ( json ) {\r\n\r\n\t\t\tPath.prototype.fromJSON.call( this, json );\r\n\r\n\t\t\tthis.uuid = json.uuid;\r\n\t\t\tthis.holes = [];\r\n\r\n\t\t\tfor ( var i = 0, l = json.holes.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar hole = json.holes[ i ];\r\n\t\t\t\tthis.holes.push( new Path().fromJSON( hole ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Light( color, intensity ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Light';\r\n\r\n\t\tthis.color = new Color( color );\r\n\t\tthis.intensity = intensity !== undefined ? intensity : 1;\r\n\r\n\t\tthis.receiveShadow = undefined;\r\n\r\n\t}\r\n\r\n\tLight.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Light,\r\n\r\n\t\tisLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tObject3D.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.color.copy( source.color );\r\n\t\t\tthis.intensity = source.intensity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.color = this.color.getHex();\r\n\t\t\tdata.object.intensity = this.intensity;\r\n\r\n\t\t\tif ( this.groundColor !== undefined ) { data.object.groundColor = this.groundColor.getHex(); }\r\n\r\n\t\t\tif ( this.distance !== undefined ) { data.object.distance = this.distance; }\r\n\t\t\tif ( this.angle !== undefined ) { data.object.angle = this.angle; }\r\n\t\t\tif ( this.decay !== undefined ) { data.object.decay = this.decay; }\r\n\t\t\tif ( this.penumbra !== undefined ) { data.object.penumbra = this.penumbra; }\r\n\r\n\t\t\tif ( this.shadow !== undefined ) { data.object.shadow = this.shadow.toJSON(); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction HemisphereLight( skyColor, groundColor, intensity ) {\r\n\r\n\t\tLight.call( this, skyColor, intensity );\r\n\r\n\t\tthis.type = 'HemisphereLight';\r\n\r\n\t\tthis.castShadow = undefined;\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.groundColor = new Color( groundColor );\r\n\r\n\t}\r\n\r\n\tHemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: HemisphereLight,\r\n\r\n\t\tisHemisphereLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.groundColor.copy( source.groundColor );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction LightShadow( camera ) {\r\n\r\n\t\tthis.camera = camera;\r\n\r\n\t\tthis.bias = 0;\r\n\t\tthis.radius = 1;\r\n\r\n\t\tthis.mapSize = new Vector2( 512, 512 );\r\n\r\n\t\tthis.map = null;\r\n\t\tthis.mapPass = null;\r\n\t\tthis.matrix = new Matrix4();\r\n\r\n\t\tthis._frustum = new Frustum();\r\n\t\tthis._frameExtents = new Vector2( 1, 1 );\r\n\r\n\t\tthis._viewportCount = 1;\r\n\r\n\t\tthis._viewports = [\r\n\r\n\t\t\tnew Vector4( 0, 0, 1, 1 )\r\n\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tObject.assign( LightShadow.prototype, {\r\n\r\n\t\t_projScreenMatrix: new Matrix4(),\r\n\r\n\t\t_lightPositionWorld: new Vector3(),\r\n\r\n\t\t_lookTarget: new Vector3(),\r\n\r\n\t\tgetViewportCount: function () {\r\n\r\n\t\t\treturn this._viewportCount;\r\n\r\n\t\t},\r\n\r\n\t\tgetFrustum: function () {\r\n\r\n\t\t\treturn this._frustum;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tvar shadowCamera = this.camera,\r\n\t\t\t\tshadowMatrix = this.matrix,\r\n\t\t\t\tprojScreenMatrix = this._projScreenMatrix,\r\n\t\t\t\tlookTarget = this._lookTarget,\r\n\t\t\t\tlightPositionWorld = this._lightPositionWorld;\r\n\r\n\t\t\tlightPositionWorld.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\tshadowCamera.position.copy( lightPositionWorld );\r\n\r\n\t\t\tlookTarget.setFromMatrixPosition( light.target.matrixWorld );\r\n\t\t\tshadowCamera.lookAt( lookTarget );\r\n\t\t\tshadowCamera.updateMatrixWorld();\r\n\r\n\t\t\tprojScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );\r\n\t\t\tthis._frustum.setFromMatrix( projScreenMatrix );\r\n\r\n\t\t\tshadowMatrix.set(\r\n\t\t\t\t0.5, 0.0, 0.0, 0.5,\r\n\t\t\t\t0.0, 0.5, 0.0, 0.5,\r\n\t\t\t\t0.0, 0.0, 0.5, 0.5,\r\n\t\t\t\t0.0, 0.0, 0.0, 1.0\r\n\t\t\t);\r\n\r\n\t\t\tshadowMatrix.multiply( shadowCamera.projectionMatrix );\r\n\t\t\tshadowMatrix.multiply( shadowCamera.matrixWorldInverse );\r\n\r\n\t\t},\r\n\r\n\t\tgetViewport: function ( viewportIndex ) {\r\n\r\n\t\t\treturn this._viewports[ viewportIndex ];\r\n\r\n\t\t},\r\n\r\n\t\tgetFrameExtents: function () {\r\n\r\n\t\t\treturn this._frameExtents;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tthis.camera = source.camera.clone();\r\n\r\n\t\t\tthis.bias = source.bias;\r\n\t\t\tthis.radius = source.radius;\r\n\r\n\t\t\tthis.mapSize.copy( source.mapSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar object = {};\r\n\r\n\t\t\tif ( this.bias !== 0 ) { object.bias = this.bias; }\r\n\t\t\tif ( this.radius !== 1 ) { object.radius = this.radius; }\r\n\t\t\tif ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) { object.mapSize = this.mapSize.toArray(); }\r\n\r\n\t\t\tobject.camera = this.camera.toJSON( false ).object;\r\n\t\t\tdelete object.camera.matrix;\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction SpotLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) );\r\n\r\n\t}\r\n\r\n\tSpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: SpotLightShadow,\r\n\r\n\t\tisSpotLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tvar camera = this.camera;\r\n\r\n\t\t\tvar fov = _Math.RAD2DEG * 2 * light.angle;\r\n\t\t\tvar aspect = this.mapSize.width / this.mapSize.height;\r\n\t\t\tvar far = light.distance || camera.far;\r\n\r\n\t\t\tif ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {\r\n\r\n\t\t\t\tcamera.fov = fov;\r\n\t\t\t\tcamera.aspect = aspect;\r\n\t\t\t\tcamera.far = far;\r\n\t\t\t\tcamera.updateProjectionMatrix();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tLightShadow.prototype.updateMatrices.call( this, light );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction SpotLight( color, intensity, distance, angle, penumbra, decay ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'SpotLight';\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.target = new Object3D();\r\n\r\n\t\tObject.defineProperty( this, 'power', {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\treturn this.intensity * Math.PI;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( power ) {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\tthis.intensity = power / Math.PI;\r\n\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.distance = ( distance !== undefined ) ? distance : 0;\r\n\t\tthis.angle = ( angle !== undefined ) ? angle : Math.PI / 3;\r\n\t\tthis.penumbra = ( penumbra !== undefined ) ? penumbra : 0;\r\n\t\tthis.decay = ( decay !== undefined ) ? decay : 1;\t// for physically correct lights, should be 2.\r\n\r\n\t\tthis.shadow = new SpotLightShadow();\r\n\r\n\t}\r\n\r\n\tSpotLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: SpotLight,\r\n\r\n\t\tisSpotLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.distance = source.distance;\r\n\t\t\tthis.angle = source.angle;\r\n\t\t\tthis.penumbra = source.penumbra;\r\n\t\t\tthis.decay = source.decay;\r\n\r\n\t\t\tthis.target = source.target.clone();\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tfunction PointLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new PerspectiveCamera( 90, 1, 0.5, 500 ) );\r\n\r\n\t\tthis._frameExtents = new Vector2( 4, 2 );\r\n\r\n\t\tthis._viewportCount = 6;\r\n\r\n\t\tthis._viewports = [\r\n\t\t\t// These viewports map a cube-map onto a 2D texture with the\r\n\t\t\t// following orientation:\r\n\t\t\t//\r\n\t\t\t// xzXZ\r\n\t\t\t// y Y\r\n\t\t\t//\r\n\t\t\t// X - Positive x direction\r\n\t\t\t// x - Negative x direction\r\n\t\t\t// Y - Positive y direction\r\n\t\t\t// y - Negative y direction\r\n\t\t\t// Z - Positive z direction\r\n\t\t\t// z - Negative z direction\r\n\r\n\t\t\t// positive X\r\n\t\t\tnew Vector4( 2, 1, 1, 1 ),\r\n\t\t\t// negative X\r\n\t\t\tnew Vector4( 0, 1, 1, 1 ),\r\n\t\t\t// positive Z\r\n\t\t\tnew Vector4( 3, 1, 1, 1 ),\r\n\t\t\t// negative Z\r\n\t\t\tnew Vector4( 1, 1, 1, 1 ),\r\n\t\t\t// positive Y\r\n\t\t\tnew Vector4( 3, 0, 1, 1 ),\r\n\t\t\t// negative Y\r\n\t\t\tnew Vector4( 1, 0, 1, 1 )\r\n\t\t];\r\n\r\n\t\tthis._cubeDirections = [\r\n\t\t\tnew Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),\r\n\t\t\tnew Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )\r\n\t\t];\r\n\r\n\t\tthis._cubeUps = [\r\n\t\t\tnew Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),\r\n\t\t\tnew Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ),\tnew Vector3( 0, 0, - 1 )\r\n\t\t];\r\n\r\n\t}\r\n\r\n\tPointLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: PointLightShadow,\r\n\r\n\t\tisPointLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light, viewportIndex ) {\r\n\r\n\t\t\tif ( viewportIndex === undefined ) { viewportIndex = 0; }\r\n\r\n\t\t\tvar camera = this.camera,\r\n\t\t\t\tshadowMatrix = this.matrix,\r\n\t\t\t\tlightPositionWorld = this._lightPositionWorld,\r\n\t\t\t\tlookTarget = this._lookTarget,\r\n\t\t\t\tprojScreenMatrix = this._projScreenMatrix;\r\n\r\n\t\t\tlightPositionWorld.setFromMatrixPosition( light.matrixWorld );\r\n\t\t\tcamera.position.copy( lightPositionWorld );\r\n\r\n\t\t\tlookTarget.copy( camera.position );\r\n\t\t\tlookTarget.add( this._cubeDirections[ viewportIndex ] );\r\n\t\t\tcamera.up.copy( this._cubeUps[ viewportIndex ] );\r\n\t\t\tcamera.lookAt( lookTarget );\r\n\t\t\tcamera.updateMatrixWorld();\r\n\r\n\t\t\tshadowMatrix.makeTranslation( - lightPositionWorld.x, - lightPositionWorld.y, - lightPositionWorld.z );\r\n\r\n\t\t\tprojScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\r\n\t\t\tthis._frustum.setFromMatrix( projScreenMatrix );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction PointLight( color, intensity, distance, decay ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'PointLight';\r\n\r\n\t\tObject.defineProperty( this, 'power', {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\treturn this.intensity * 4 * Math.PI;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( power ) {\r\n\r\n\t\t\t\t// intensity = power per solid angle.\r\n\t\t\t\t// ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\r\n\t\t\t\tthis.intensity = power / ( 4 * Math.PI );\r\n\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t\tthis.distance = ( distance !== undefined ) ? distance : 0;\r\n\t\tthis.decay = ( decay !== undefined ) ? decay : 1;\t// for physically correct lights, should be 2.\r\n\r\n\t\tthis.shadow = new PointLightShadow();\r\n\r\n\t}\r\n\r\n\tPointLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: PointLight,\r\n\r\n\t\tisPointLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.distance = source.distance;\r\n\t\t\tthis.decay = source.decay;\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author arose / http://github.com/arose\r\n\t */\r\n\r\n\tfunction OrthographicCamera( left, right, top, bottom, near, far ) {\r\n\r\n\t\tCamera.call( this );\r\n\r\n\t\tthis.type = 'OrthographicCamera';\r\n\r\n\t\tthis.zoom = 1;\r\n\t\tthis.view = null;\r\n\r\n\t\tthis.left = ( left !== undefined ) ? left : - 1;\r\n\t\tthis.right = ( right !== undefined ) ? right : 1;\r\n\t\tthis.top = ( top !== undefined ) ? top : 1;\r\n\t\tthis.bottom = ( bottom !== undefined ) ? bottom : - 1;\r\n\r\n\t\tthis.near = ( near !== undefined ) ? near : 0.1;\r\n\t\tthis.far = ( far !== undefined ) ? far : 2000;\r\n\r\n\t\tthis.updateProjectionMatrix();\r\n\r\n\t}\r\n\r\n\tOrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\r\n\r\n\t\tconstructor: OrthographicCamera,\r\n\r\n\t\tisOrthographicCamera: true,\r\n\r\n\t\tcopy: function ( source, recursive ) {\r\n\r\n\t\t\tCamera.prototype.copy.call( this, source, recursive );\r\n\r\n\t\t\tthis.left = source.left;\r\n\t\t\tthis.right = source.right;\r\n\t\t\tthis.top = source.top;\r\n\t\t\tthis.bottom = source.bottom;\r\n\t\t\tthis.near = source.near;\r\n\t\t\tthis.far = source.far;\r\n\r\n\t\t\tthis.zoom = source.zoom;\r\n\t\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\r\n\r\n\t\t\tif ( this.view === null ) {\r\n\r\n\t\t\t\tthis.view = {\r\n\t\t\t\t\tenabled: true,\r\n\t\t\t\t\tfullWidth: 1,\r\n\t\t\t\t\tfullHeight: 1,\r\n\t\t\t\t\toffsetX: 0,\r\n\t\t\t\t\toffsetY: 0,\r\n\t\t\t\t\twidth: 1,\r\n\t\t\t\t\theight: 1\r\n\t\t\t\t};\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.view.enabled = true;\r\n\t\t\tthis.view.fullWidth = fullWidth;\r\n\t\t\tthis.view.fullHeight = fullHeight;\r\n\t\t\tthis.view.offsetX = x;\r\n\t\t\tthis.view.offsetY = y;\r\n\t\t\tthis.view.width = width;\r\n\t\t\tthis.view.height = height;\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tclearViewOffset: function () {\r\n\r\n\t\t\tif ( this.view !== null ) {\r\n\r\n\t\t\t\tthis.view.enabled = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.updateProjectionMatrix();\r\n\r\n\t\t},\r\n\r\n\t\tupdateProjectionMatrix: function () {\r\n\r\n\t\t\tvar dx = ( this.right - this.left ) / ( 2 * this.zoom );\r\n\t\t\tvar dy = ( this.top - this.bottom ) / ( 2 * this.zoom );\r\n\t\t\tvar cx = ( this.right + this.left ) / 2;\r\n\t\t\tvar cy = ( this.top + this.bottom ) / 2;\r\n\r\n\t\t\tvar left = cx - dx;\r\n\t\t\tvar right = cx + dx;\r\n\t\t\tvar top = cy + dy;\r\n\t\t\tvar bottom = cy - dy;\r\n\r\n\t\t\tif ( this.view !== null && this.view.enabled ) {\r\n\r\n\t\t\t\tvar zoomW = this.zoom / ( this.view.width / this.view.fullWidth );\r\n\t\t\t\tvar zoomH = this.zoom / ( this.view.height / this.view.fullHeight );\r\n\t\t\t\tvar scaleW = ( this.right - this.left ) / this.view.width;\r\n\t\t\t\tvar scaleH = ( this.top - this.bottom ) / this.view.height;\r\n\r\n\t\t\t\tleft += scaleW * ( this.view.offsetX / zoomW );\r\n\t\t\t\tright = left + scaleW * ( this.view.width / zoomW );\r\n\t\t\t\ttop -= scaleH * ( this.view.offsetY / zoomH );\r\n\t\t\t\tbottom = top - scaleH * ( this.view.height / zoomH );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far );\r\n\r\n\t\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.zoom = this.zoom;\r\n\t\t\tdata.object.left = this.left;\r\n\t\t\tdata.object.right = this.right;\r\n\t\t\tdata.object.top = this.top;\r\n\t\t\tdata.object.bottom = this.bottom;\r\n\t\t\tdata.object.near = this.near;\r\n\t\t\tdata.object.far = this.far;\r\n\r\n\t\t\tif ( this.view !== null ) { data.object.view = Object.assign( {}, this.view ); }\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction DirectionalLightShadow() {\r\n\r\n\t\tLightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );\r\n\r\n\t}\r\n\r\n\tDirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), {\r\n\r\n\t\tconstructor: DirectionalLightShadow,\r\n\r\n\t\tisDirectionalLightShadow: true,\r\n\r\n\t\tupdateMatrices: function ( light ) {\r\n\r\n\t\t\tLightShadow.prototype.updateMatrices.call( this, light );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction DirectionalLight( color, intensity ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'DirectionalLight';\r\n\r\n\t\tthis.position.copy( Object3D.DefaultUp );\r\n\t\tthis.updateMatrix();\r\n\r\n\t\tthis.target = new Object3D();\r\n\r\n\t\tthis.shadow = new DirectionalLightShadow();\r\n\r\n\t}\r\n\r\n\tDirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: DirectionalLight,\r\n\r\n\t\tisDirectionalLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.target = source.target.clone();\r\n\r\n\t\t\tthis.shadow = source.shadow.clone();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AmbientLight( color, intensity ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'AmbientLight';\r\n\r\n\t\tthis.castShadow = undefined;\r\n\r\n\t}\r\n\r\n\tAmbientLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: AmbientLight,\r\n\r\n\t\tisAmbientLight: true\r\n\r\n\t} );\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t */\r\n\r\n\tfunction RectAreaLight( color, intensity, width, height ) {\r\n\r\n\t\tLight.call( this, color, intensity );\r\n\r\n\t\tthis.type = 'RectAreaLight';\r\n\r\n\t\tthis.width = ( width !== undefined ) ? width : 10;\r\n\t\tthis.height = ( height !== undefined ) ? height : 10;\r\n\r\n\t}\r\n\r\n\tRectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: RectAreaLight,\r\n\r\n\t\tisRectAreaLight: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.width = source.width;\r\n\t\t\tthis.height = source.height;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Light.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\tdata.object.width = this.width;\r\n\t\t\tdata.object.height = this.height;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction MaterialLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t\tthis.textures = {};\r\n\r\n\t}\r\n\r\n\tMaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: MaterialLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar textures = this.textures;\r\n\r\n\t\t\tfunction getTexture( name ) {\r\n\r\n\t\t\t\tif ( textures[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.MaterialLoader: Undefined texture', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn textures[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar material = new Materials[ json.type ]();\r\n\r\n\t\t\tif ( json.uuid !== undefined ) { material.uuid = json.uuid; }\r\n\t\t\tif ( json.name !== undefined ) { material.name = json.name; }\r\n\t\t\tif ( json.color !== undefined ) { material.color.setHex( json.color ); }\r\n\t\t\tif ( json.roughness !== undefined ) { material.roughness = json.roughness; }\r\n\t\t\tif ( json.metalness !== undefined ) { material.metalness = json.metalness; }\r\n\t\t\tif ( json.sheen !== undefined ) { material.sheen = new Color().setHex( json.sheen ); }\r\n\t\t\tif ( json.emissive !== undefined ) { material.emissive.setHex( json.emissive ); }\r\n\t\t\tif ( json.specular !== undefined ) { material.specular.setHex( json.specular ); }\r\n\t\t\tif ( json.shininess !== undefined ) { material.shininess = json.shininess; }\r\n\t\t\tif ( json.clearcoat !== undefined ) { material.clearcoat = json.clearcoat; }\r\n\t\t\tif ( json.clearcoatRoughness !== undefined ) { material.clearcoatRoughness = json.clearcoatRoughness; }\r\n\t\t\tif ( json.vertexColors !== undefined ) { material.vertexColors = json.vertexColors; }\r\n\t\t\tif ( json.fog !== undefined ) { material.fog = json.fog; }\r\n\t\t\tif ( json.flatShading !== undefined ) { material.flatShading = json.flatShading; }\r\n\t\t\tif ( json.blending !== undefined ) { material.blending = json.blending; }\r\n\t\t\tif ( json.combine !== undefined ) { material.combine = json.combine; }\r\n\t\t\tif ( json.side !== undefined ) { material.side = json.side; }\r\n\t\t\tif ( json.opacity !== undefined ) { material.opacity = json.opacity; }\r\n\t\t\tif ( json.transparent !== undefined ) { material.transparent = json.transparent; }\r\n\t\t\tif ( json.alphaTest !== undefined ) { material.alphaTest = json.alphaTest; }\r\n\t\t\tif ( json.depthTest !== undefined ) { material.depthTest = json.depthTest; }\r\n\t\t\tif ( json.depthWrite !== undefined ) { material.depthWrite = json.depthWrite; }\r\n\t\t\tif ( json.colorWrite !== undefined ) { material.colorWrite = json.colorWrite; }\r\n\r\n\t\t\tif ( json.stencilWrite !== undefined ) { material.stencilWrite = json.stencilWrite; }\r\n\t\t\tif ( json.stencilWriteMask !== undefined ) { material.stencilWriteMask = json.stencilWriteMask; }\r\n\t\t\tif ( json.stencilFunc !== undefined ) { material.stencilFunc = json.stencilFunc; }\r\n\t\t\tif ( json.stencilRef !== undefined ) { material.stencilRef = json.stencilRef; }\r\n\t\t\tif ( json.stencilFuncMask !== undefined ) { material.stencilFuncMask = json.stencilFuncMask; }\r\n\t\t\tif ( json.stencilFail !== undefined ) { material.stencilFail = json.stencilFail; }\r\n\t\t\tif ( json.stencilZFail !== undefined ) { material.stencilZFail = json.stencilZFail; }\r\n\t\t\tif ( json.stencilZPass !== undefined ) { material.stencilZPass = json.stencilZPass; }\r\n\r\n\t\t\tif ( json.wireframe !== undefined ) { material.wireframe = json.wireframe; }\r\n\t\t\tif ( json.wireframeLinewidth !== undefined ) { material.wireframeLinewidth = json.wireframeLinewidth; }\r\n\t\t\tif ( json.wireframeLinecap !== undefined ) { material.wireframeLinecap = json.wireframeLinecap; }\r\n\t\t\tif ( json.wireframeLinejoin !== undefined ) { material.wireframeLinejoin = json.wireframeLinejoin; }\r\n\r\n\t\t\tif ( json.rotation !== undefined ) { material.rotation = json.rotation; }\r\n\r\n\t\t\tif ( json.linewidth !== 1 ) { material.linewidth = json.linewidth; }\r\n\t\t\tif ( json.dashSize !== undefined ) { material.dashSize = json.dashSize; }\r\n\t\t\tif ( json.gapSize !== undefined ) { material.gapSize = json.gapSize; }\r\n\t\t\tif ( json.scale !== undefined ) { material.scale = json.scale; }\r\n\r\n\t\t\tif ( json.polygonOffset !== undefined ) { material.polygonOffset = json.polygonOffset; }\r\n\t\t\tif ( json.polygonOffsetFactor !== undefined ) { material.polygonOffsetFactor = json.polygonOffsetFactor; }\r\n\t\t\tif ( json.polygonOffsetUnits !== undefined ) { material.polygonOffsetUnits = json.polygonOffsetUnits; }\r\n\r\n\t\t\tif ( json.skinning !== undefined ) { material.skinning = json.skinning; }\r\n\t\t\tif ( json.morphTargets !== undefined ) { material.morphTargets = json.morphTargets; }\r\n\t\t\tif ( json.morphNormals !== undefined ) { material.morphNormals = json.morphNormals; }\r\n\t\t\tif ( json.dithering !== undefined ) { material.dithering = json.dithering; }\r\n\r\n\t\t\tif ( json.visible !== undefined ) { material.visible = json.visible; }\r\n\r\n\t\t\tif ( json.toneMapped !== undefined ) { material.toneMapped = json.toneMapped; }\r\n\r\n\t\t\tif ( json.userData !== undefined ) { material.userData = json.userData; }\r\n\r\n\t\t\t// Shader Material\r\n\r\n\t\t\tif ( json.uniforms !== undefined ) {\r\n\r\n\t\t\t\tfor ( var name in json.uniforms ) {\r\n\r\n\t\t\t\t\tvar uniform = json.uniforms[ name ];\r\n\r\n\t\t\t\t\tmaterial.uniforms[ name ] = {};\r\n\r\n\t\t\t\t\tswitch ( uniform.type ) {\r\n\r\n\t\t\t\t\t\tcase 't':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = getTexture( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'c':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Color().setHex( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v2':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector2().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v3':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector3().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'v4':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Vector4().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'm3':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );\r\n\r\n\t\t\t\t\t\tcase 'm4':\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tmaterial.uniforms[ name ].value = uniform.value;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.defines !== undefined ) { material.defines = json.defines; }\r\n\t\t\tif ( json.vertexShader !== undefined ) { material.vertexShader = json.vertexShader; }\r\n\t\t\tif ( json.fragmentShader !== undefined ) { material.fragmentShader = json.fragmentShader; }\r\n\r\n\t\t\tif ( json.extensions !== undefined ) {\r\n\r\n\t\t\t\tfor ( var key in json.extensions ) {\r\n\r\n\t\t\t\t\tmaterial.extensions[ key ] = json.extensions[ key ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Deprecated\r\n\r\n\t\t\tif ( json.shading !== undefined ) { material.flatShading = json.shading === 1; } // THREE.FlatShading\r\n\r\n\t\t\t// for PointsMaterial\r\n\r\n\t\t\tif ( json.size !== undefined ) { material.size = json.size; }\r\n\t\t\tif ( json.sizeAttenuation !== undefined ) { material.sizeAttenuation = json.sizeAttenuation; }\r\n\r\n\t\t\t// maps\r\n\r\n\t\t\tif ( json.map !== undefined ) { material.map = getTexture( json.map ); }\r\n\t\t\tif ( json.matcap !== undefined ) { material.matcap = getTexture( json.matcap ); }\r\n\r\n\t\t\tif ( json.alphaMap !== undefined ) {\r\n\r\n\t\t\t\tmaterial.alphaMap = getTexture( json.alphaMap );\r\n\t\t\t\tmaterial.transparent = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.bumpMap !== undefined ) { material.bumpMap = getTexture( json.bumpMap ); }\r\n\t\t\tif ( json.bumpScale !== undefined ) { material.bumpScale = json.bumpScale; }\r\n\r\n\t\t\tif ( json.normalMap !== undefined ) { material.normalMap = getTexture( json.normalMap ); }\r\n\t\t\tif ( json.normalMapType !== undefined ) { material.normalMapType = json.normalMapType; }\r\n\t\t\tif ( json.normalScale !== undefined ) {\r\n\r\n\t\t\t\tvar normalScale = json.normalScale;\r\n\r\n\t\t\t\tif ( Array.isArray( normalScale ) === false ) {\r\n\r\n\t\t\t\t\t// Blender exporter used to export a scalar. See #7459\r\n\r\n\t\t\t\t\tnormalScale = [ normalScale, normalScale ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmaterial.normalScale = new Vector2().fromArray( normalScale );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.displacementMap !== undefined ) { material.displacementMap = getTexture( json.displacementMap ); }\r\n\t\t\tif ( json.displacementScale !== undefined ) { material.displacementScale = json.displacementScale; }\r\n\t\t\tif ( json.displacementBias !== undefined ) { material.displacementBias = json.displacementBias; }\r\n\r\n\t\t\tif ( json.roughnessMap !== undefined ) { material.roughnessMap = getTexture( json.roughnessMap ); }\r\n\t\t\tif ( json.metalnessMap !== undefined ) { material.metalnessMap = getTexture( json.metalnessMap ); }\r\n\r\n\t\t\tif ( json.emissiveMap !== undefined ) { material.emissiveMap = getTexture( json.emissiveMap ); }\r\n\t\t\tif ( json.emissiveIntensity !== undefined ) { material.emissiveIntensity = json.emissiveIntensity; }\r\n\r\n\t\t\tif ( json.specularMap !== undefined ) { material.specularMap = getTexture( json.specularMap ); }\r\n\r\n\t\t\tif ( json.envMap !== undefined ) { material.envMap = getTexture( json.envMap ); }\r\n\t\t\tif ( json.envMapIntensity !== undefined ) { material.envMapIntensity = json.envMapIntensity; }\r\n\r\n\t\t\tif ( json.reflectivity !== undefined ) { material.reflectivity = json.reflectivity; }\r\n\t\t\tif ( json.refractionRatio !== undefined ) { material.refractionRatio = json.refractionRatio; }\r\n\r\n\t\t\tif ( json.lightMap !== undefined ) { material.lightMap = getTexture( json.lightMap ); }\r\n\t\t\tif ( json.lightMapIntensity !== undefined ) { material.lightMapIntensity = json.lightMapIntensity; }\r\n\r\n\t\t\tif ( json.aoMap !== undefined ) { material.aoMap = getTexture( json.aoMap ); }\r\n\t\t\tif ( json.aoMapIntensity !== undefined ) { material.aoMapIntensity = json.aoMapIntensity; }\r\n\r\n\t\t\tif ( json.gradientMap !== undefined ) { material.gradientMap = getTexture( json.gradientMap ); }\r\n\r\n\t\t\tif ( json.clearcoatNormalMap !== undefined ) { material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); }\r\n\t\t\tif ( json.clearcoatNormalScale !== undefined ) { material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); }\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t},\r\n\r\n\t\tsetTextures: function ( value ) {\r\n\r\n\t\t\tthis.textures = value;\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Don McCurdy / https://www.donmccurdy.com\r\n\t */\r\n\r\n\tvar LoaderUtils = {\r\n\r\n\t\tdecodeText: function ( array ) {\r\n\r\n\t\t\tif ( typeof TextDecoder !== 'undefined' ) {\r\n\r\n\t\t\t\treturn new TextDecoder().decode( array );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Avoid the String.fromCharCode.apply(null, array) shortcut, which\r\n\t\t\t// throws a \"maximum call stack size exceeded\" error for large arrays.\r\n\r\n\t\t\tvar s = '';\r\n\r\n\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t// Implicitly assumes little-endian.\r\n\t\t\t\ts += String.fromCharCode( array[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttry {\r\n\r\n\t\t\t\t// merges multi-byte utf-8 characters.\r\n\r\n\t\t\t\treturn decodeURIComponent( escape( s ) );\r\n\r\n\t\t\t} catch ( e ) { // see #16358\r\n\r\n\t\t\t\treturn s;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\textractUrlBase: function ( url ) {\r\n\r\n\t\t\tvar index = url.lastIndexOf( '/' );\r\n\r\n\t\t\tif ( index === - 1 ) { return './'; }\r\n\r\n\t\t\treturn url.substr( 0, index + 1 );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedBufferGeometry() {\r\n\r\n\t\tBufferGeometry.call( this );\r\n\r\n\t\tthis.type = 'InstancedBufferGeometry';\r\n\t\tthis.maxInstancedCount = undefined;\r\n\r\n\t}\r\n\r\n\tInstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), {\r\n\r\n\t\tconstructor: InstancedBufferGeometry,\r\n\r\n\t\tisInstancedBufferGeometry: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tBufferGeometry.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.maxInstancedCount = source.maxInstancedCount;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function () {\r\n\r\n\t\t\tvar data = BufferGeometry.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.maxInstancedCount = this.maxInstancedCount;\r\n\r\n\t\t\tdata.isInstancedBufferGeometry = true;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedBufferAttribute( array, itemSize, normalized, meshPerAttribute ) {\r\n\r\n\t\tif ( typeof ( normalized ) === 'number' ) {\r\n\r\n\t\t\tmeshPerAttribute = normalized;\r\n\r\n\t\t\tnormalized = false;\r\n\r\n\t\t\tconsole.error( 'THREE.InstancedBufferAttribute: The constructor now expects normalized as the third argument.' );\r\n\r\n\t\t}\r\n\r\n\t\tBufferAttribute.call( this, array, itemSize, normalized );\r\n\r\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\r\n\r\n\t}\r\n\r\n\tInstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), {\r\n\r\n\t\tconstructor: InstancedBufferAttribute,\r\n\r\n\t\tisInstancedBufferAttribute: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tBufferAttribute.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ()\t{\r\n\r\n\t\t\tvar data = BufferAttribute.prototype.toJSON.call( this );\r\n\r\n\t\t\tdata.meshPerAttribute = this.meshPerAttribute;\r\n\r\n\t\t\tdata.isInstancedBufferAttribute = true;\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction BufferGeometryLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tBufferGeometryLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: BufferGeometryLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( scope.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tonLoad( scope.parse( JSON.parse( text ) ) );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\tvar geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();\r\n\r\n\t\t\tvar index = json.data.index;\r\n\r\n\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\tvar typedArray = new TYPED_ARRAYS[ index.type ]( index.array );\r\n\t\t\t\tgeometry.setIndex( new BufferAttribute( typedArray, 1 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar attributes = json.data.attributes;\r\n\r\n\t\t\tfor ( var key in attributes ) {\r\n\r\n\t\t\t\tvar attribute = attributes[ key ];\r\n\t\t\t\tvar typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );\r\n\t\t\t\tvar bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;\r\n\t\t\t\tvar bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );\r\n\t\t\t\tif ( attribute.name !== undefined ) { bufferAttribute.name = attribute.name; }\r\n\t\t\t\tgeometry.setAttribute( key, bufferAttribute );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphAttributes = json.data.morphAttributes;\r\n\r\n\t\t\tif ( morphAttributes ) {\r\n\r\n\t\t\t\tfor ( var key in morphAttributes ) {\r\n\r\n\t\t\t\t\tvar attributeArray = morphAttributes[ key ];\r\n\r\n\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar attribute = attributeArray[ i ];\r\n\t\t\t\t\t\tvar typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array );\r\n\r\n\t\t\t\t\t\tvar bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );\r\n\t\t\t\t\t\tif ( attribute.name !== undefined ) { bufferAttribute.name = attribute.name; }\r\n\t\t\t\t\t\tarray.push( bufferAttribute );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.morphAttributes[ key ] = array;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar morphTargetsRelative = json.data.morphTargetsRelative;\r\n\r\n\t\t\tif ( morphTargetsRelative ) {\r\n\r\n\t\t\t\tgeometry.morphTargetsRelative = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar groups = json.data.groups || json.data.drawcalls || json.data.offsets;\r\n\r\n\t\t\tif ( groups !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, n = groups.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar group = groups[ i ];\r\n\r\n\t\t\t\t\tgeometry.addGroup( group.start, group.count, group.materialIndex );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar boundingSphere = json.data.boundingSphere;\r\n\r\n\t\t\tif ( boundingSphere !== undefined ) {\r\n\r\n\t\t\t\tvar center = new Vector3();\r\n\r\n\t\t\t\tif ( boundingSphere.center !== undefined ) {\r\n\r\n\t\t\t\t\tcenter.fromArray( boundingSphere.center );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.boundingSphere = new Sphere( center, boundingSphere.radius );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.name ) { geometry.name = json.name; }\r\n\t\t\tif ( json.userData ) { geometry.userData = json.userData; }\r\n\r\n\t\t\treturn geometry;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tvar TYPED_ARRAYS = {\r\n\t\tInt8Array: Int8Array,\r\n\t\tUint8Array: Uint8Array,\r\n\t\t// Workaround for IE11 pre KB2929437. See #11440\r\n\t\tUint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array,\r\n\t\tInt16Array: Int16Array,\r\n\t\tUint16Array: Uint16Array,\r\n\t\tInt32Array: Int32Array,\r\n\t\tUint32Array: Uint32Array,\r\n\t\tFloat32Array: Float32Array,\r\n\t\tFloat64Array: Float64Array\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction ObjectLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tObjectLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ObjectLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;\r\n\t\t\tthis.resourcePath = this.resourcePath || path;\r\n\r\n\t\t\tvar loader = new FileLoader( scope.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tvar json = null;\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tjson = JSON.parse( text );\r\n\r\n\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\tif ( onError !== undefined ) { onError( error ); }\r\n\r\n\t\t\t\t\tconsole.error( 'THREE:ObjectLoader: Can\\'t parse ' + url + '.', error.message );\r\n\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar metadata = json.metadata;\r\n\r\n\t\t\t\tif ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.ObjectLoader: Can\\'t load ' + url );\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.parse( json, onLoad );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json, onLoad ) {\r\n\r\n\t\t\tvar shapes = this.parseShape( json.shapes );\r\n\t\t\tvar geometries = this.parseGeometries( json.geometries, shapes );\r\n\r\n\t\t\tvar images = this.parseImages( json.images, function () {\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) { onLoad( object ); }\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tvar textures = this.parseTextures( json.textures, images );\r\n\t\t\tvar materials = this.parseMaterials( json.materials, textures );\r\n\r\n\t\t\tvar object = this.parseObject( json.object, geometries, materials );\r\n\r\n\t\t\tif ( json.animations ) {\r\n\r\n\t\t\t\tobject.animations = this.parseAnimations( json.animations );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.images === undefined || json.images.length === 0 ) {\r\n\r\n\t\t\t\tif ( onLoad !== undefined ) { onLoad( object ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t},\r\n\r\n\t\tparseShape: function ( json ) {\r\n\r\n\t\t\tvar shapes = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar shape = new Shape().fromJSON( json[ i ] );\r\n\r\n\t\t\t\t\tshapes[ shape.uuid ] = shape;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t},\r\n\r\n\t\tparseGeometries: function ( json, shapes ) {\r\n\r\n\t\t\tvar geometries = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tvar bufferGeometryLoader = new BufferGeometryLoader();\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar geometry;\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tswitch ( data.type ) {\r\n\r\n\t\t\t\t\t\tcase 'PlaneGeometry':\r\n\t\t\t\t\t\tcase 'PlaneBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.width,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'BoxGeometry':\r\n\t\t\t\t\t\tcase 'BoxBufferGeometry':\r\n\t\t\t\t\t\tcase 'CubeGeometry': // backwards compatible\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.width,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.depth,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.depthSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'CircleGeometry':\r\n\t\t\t\t\t\tcase 'CircleBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.segments,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'CylinderGeometry':\r\n\t\t\t\t\t\tcase 'CylinderBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radiusTop,\r\n\t\t\t\t\t\t\t\tdata.radiusBottom,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.openEnded,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'ConeGeometry':\r\n\t\t\t\t\t\tcase 'ConeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.height,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.openEnded,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'SphereGeometry':\r\n\t\t\t\t\t\tcase 'SphereBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.widthSegments,\r\n\t\t\t\t\t\t\t\tdata.heightSegments,\r\n\t\t\t\t\t\t\t\tdata.phiStart,\r\n\t\t\t\t\t\t\t\tdata.phiLength,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'DodecahedronGeometry':\r\n\t\t\t\t\t\tcase 'DodecahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'IcosahedronGeometry':\r\n\t\t\t\t\t\tcase 'IcosahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'OctahedronGeometry':\r\n\t\t\t\t\t\tcase 'OctahedronBufferGeometry':\r\n\t\t\t\t\t\tcase 'TetrahedronGeometry':\r\n\t\t\t\t\t\tcase 'TetrahedronBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.detail\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'RingGeometry':\r\n\t\t\t\t\t\tcase 'RingBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.innerRadius,\r\n\t\t\t\t\t\t\t\tdata.outerRadius,\r\n\t\t\t\t\t\t\t\tdata.thetaSegments,\r\n\t\t\t\t\t\t\t\tdata.phiSegments,\r\n\t\t\t\t\t\t\t\tdata.thetaStart,\r\n\t\t\t\t\t\t\t\tdata.thetaLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TorusGeometry':\r\n\t\t\t\t\t\tcase 'TorusBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.tube,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.arc\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TorusKnotGeometry':\r\n\t\t\t\t\t\tcase 'TorusKnotBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.tube,\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.p,\r\n\t\t\t\t\t\t\t\tdata.q\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'TubeGeometry':\r\n\t\t\t\t\t\tcase 'TubeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\t// This only works for built-in curves (e.g. CatmullRomCurve3).\r\n\t\t\t\t\t\t\t// User defined curves or instances of CurvePath will not be deserialized.\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tnew Curves[ data.path.type ]().fromJSON( data.path ),\r\n\t\t\t\t\t\t\t\tdata.tubularSegments,\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.radialSegments,\r\n\t\t\t\t\t\t\t\tdata.closed\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'LatheGeometry':\r\n\t\t\t\t\t\tcase 'LatheBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.points,\r\n\t\t\t\t\t\t\t\tdata.segments,\r\n\t\t\t\t\t\t\t\tdata.phiStart,\r\n\t\t\t\t\t\t\t\tdata.phiLength\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'PolyhedronGeometry':\r\n\t\t\t\t\t\tcase 'PolyhedronBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tdata.vertices,\r\n\t\t\t\t\t\t\t\tdata.indices,\r\n\t\t\t\t\t\t\t\tdata.radius,\r\n\t\t\t\t\t\t\t\tdata.details\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'ShapeGeometry':\r\n\t\t\t\t\t\tcase 'ShapeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tvar geometryShapes = [];\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar shape = shapes[ data.shapes[ j ] ];\r\n\r\n\t\t\t\t\t\t\t\tgeometryShapes.push( shape );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tgeometryShapes,\r\n\t\t\t\t\t\t\t\tdata.curveSegments\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\r\n\t\t\t\t\t\tcase 'ExtrudeGeometry':\r\n\t\t\t\t\t\tcase 'ExtrudeBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tvar geometryShapes = [];\r\n\r\n\t\t\t\t\t\t\tfor ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\t\tvar shape = shapes[ data.shapes[ j ] ];\r\n\r\n\t\t\t\t\t\t\t\tgeometryShapes.push( shape );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tvar extrudePath = data.options.extrudePath;\r\n\r\n\t\t\t\t\t\t\tif ( extrudePath !== undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tdata.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tgeometry = new Geometries[ data.type ](\r\n\t\t\t\t\t\t\t\tgeometryShapes,\r\n\t\t\t\t\t\t\t\tdata.options\r\n\t\t\t\t\t\t\t);\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'BufferGeometry':\r\n\t\t\t\t\t\tcase 'InstancedBufferGeometry':\r\n\r\n\t\t\t\t\t\t\tgeometry = bufferGeometryLoader.parse( data );\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'Geometry':\r\n\r\n\t\t\t\t\t\t\tif ( 'THREE' in window && 'LegacyJSONLoader' in THREE ) {\r\n\r\n\t\t\t\t\t\t\t\tvar geometryLoader = new THREE.LegacyJSONLoader();\r\n\t\t\t\t\t\t\t\tgeometry = geometryLoader.parse( data, this.resourcePath ).geometry;\r\n\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tconsole.error( 'THREE.ObjectLoader: You have to import LegacyJSONLoader in order load geometry data of type \"Geometry\".' );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Unsupported geometry type \"' + data.type + '\"' );\r\n\r\n\t\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tgeometry.uuid = data.uuid;\r\n\r\n\t\t\t\t\tif ( data.name !== undefined ) { geometry.name = data.name; }\r\n\t\t\t\t\tif ( geometry.isBufferGeometry === true && data.userData !== undefined ) { geometry.userData = data.userData; }\r\n\r\n\t\t\t\t\tgeometries[ data.uuid ] = geometry;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometries;\r\n\r\n\t\t},\r\n\r\n\t\tparseMaterials: function ( json, textures ) {\r\n\r\n\t\t\tvar cache = {}; // MultiMaterial\r\n\t\t\tvar materials = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tvar loader = new MaterialLoader();\r\n\t\t\t\tloader.setTextures( textures );\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tif ( data.type === 'MultiMaterial' ) {\r\n\r\n\t\t\t\t\t\t// Deprecated\r\n\r\n\t\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\t\tfor ( var j = 0; j < data.materials.length; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar material = data.materials[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( cache[ material.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\t\tcache[ material.uuid ] = loader.parse( material );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\tarray.push( cache[ material.uuid ] );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tmaterials[ data.uuid ] = array;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( cache[ data.uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tcache[ data.uuid ] = loader.parse( data );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tmaterials[ data.uuid ] = cache[ data.uuid ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn materials;\r\n\r\n\t\t},\r\n\r\n\t\tparseAnimations: function ( json ) {\r\n\r\n\t\t\tvar animations = [];\r\n\r\n\t\t\tfor ( var i = 0; i < json.length; i ++ ) {\r\n\r\n\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\tvar clip = AnimationClip.parse( data );\r\n\r\n\t\t\t\tif ( data.uuid !== undefined ) { clip.uuid = data.uuid; }\r\n\r\n\t\t\t\tanimations.push( clip );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn animations;\r\n\r\n\t\t},\r\n\r\n\t\tparseImages: function ( json, onLoad ) {\r\n\r\n\t\t\tvar scope = this;\r\n\t\t\tvar images = {};\r\n\r\n\t\t\tfunction loadImage( url ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\treturn loader.load( url, function () {\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, undefined, function () {\r\n\r\n\t\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json !== undefined && json.length > 0 ) {\r\n\r\n\t\t\t\tvar manager = new LoadingManager( onLoad );\r\n\r\n\t\t\t\tvar loader = new ImageLoader( manager );\r\n\t\t\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\t\t\tfor ( var i = 0, il = json.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar image = json[ i ];\r\n\t\t\t\t\tvar url = image.url;\r\n\r\n\t\t\t\t\tif ( Array.isArray( url ) ) {\r\n\r\n\t\t\t\t\t\t// load array of images e.g CubeTexture\r\n\r\n\t\t\t\t\t\timages[ image.uuid ] = [];\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = url.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar currentUrl = url[ j ];\r\n\r\n\t\t\t\t\t\t\tvar path = /^(\\/\\/)|([a-z]+:(\\/\\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;\r\n\r\n\t\t\t\t\t\t\timages[ image.uuid ].push( loadImage( path ) );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// load single image\r\n\r\n\t\t\t\t\t\tvar path = /^(\\/\\/)|([a-z]+:(\\/\\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;\r\n\r\n\t\t\t\t\t\timages[ image.uuid ] = loadImage( path );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn images;\r\n\r\n\t\t},\r\n\r\n\t\tparseTextures: function ( json, images ) {\r\n\r\n\t\t\tfunction parseConstant( value, type ) {\r\n\r\n\t\t\t\tif ( typeof value === 'number' ) { return value; }\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );\r\n\r\n\t\t\t\treturn type[ value ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar textures = {};\r\n\r\n\t\t\tif ( json !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0, l = json.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar data = json[ i ];\r\n\r\n\t\t\t\t\tif ( data.image === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: No \"image\" specified for', data.uuid );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( images[ data.image ] === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined image', data.image );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar texture;\r\n\r\n\t\t\t\t\tif ( Array.isArray( images[ data.image ] ) ) {\r\n\r\n\t\t\t\t\t\ttexture = new CubeTexture( images[ data.image ] );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\ttexture = new Texture( images[ data.image ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttexture.needsUpdate = true;\r\n\r\n\t\t\t\t\ttexture.uuid = data.uuid;\r\n\r\n\t\t\t\t\tif ( data.name !== undefined ) { texture.name = data.name; }\r\n\r\n\t\t\t\t\tif ( data.mapping !== undefined ) { texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); }\r\n\r\n\t\t\t\t\tif ( data.offset !== undefined ) { texture.offset.fromArray( data.offset ); }\r\n\t\t\t\t\tif ( data.repeat !== undefined ) { texture.repeat.fromArray( data.repeat ); }\r\n\t\t\t\t\tif ( data.center !== undefined ) { texture.center.fromArray( data.center ); }\r\n\t\t\t\t\tif ( data.rotation !== undefined ) { texture.rotation = data.rotation; }\r\n\r\n\t\t\t\t\tif ( data.wrap !== undefined ) {\r\n\r\n\t\t\t\t\t\ttexture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );\r\n\t\t\t\t\t\ttexture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( data.format !== undefined ) { texture.format = data.format; }\r\n\t\t\t\t\tif ( data.type !== undefined ) { texture.type = data.type; }\r\n\t\t\t\t\tif ( data.encoding !== undefined ) { texture.encoding = data.encoding; }\r\n\r\n\t\t\t\t\tif ( data.minFilter !== undefined ) { texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); }\r\n\t\t\t\t\tif ( data.magFilter !== undefined ) { texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); }\r\n\t\t\t\t\tif ( data.anisotropy !== undefined ) { texture.anisotropy = data.anisotropy; }\r\n\r\n\t\t\t\t\tif ( data.flipY !== undefined ) { texture.flipY = data.flipY; }\r\n\r\n\t\t\t\t\tif ( data.premultiplyAlpha !== undefined ) { texture.premultiplyAlpha = data.premultiplyAlpha; }\r\n\t\t\t\t\tif ( data.unpackAlignment !== undefined ) { texture.unpackAlignment = data.unpackAlignment; }\r\n\r\n\t\t\t\t\ttextures[ data.uuid ] = texture;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn textures;\r\n\r\n\t\t},\r\n\r\n\t\tparseObject: function ( data, geometries, materials ) {\r\n\r\n\t\t\tvar object;\r\n\r\n\t\t\tfunction getGeometry( name ) {\r\n\r\n\t\t\t\tif ( geometries[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined geometry', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn geometries[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction getMaterial( name ) {\r\n\r\n\t\t\t\tif ( name === undefined ) { return undefined; }\r\n\r\n\t\t\t\tif ( Array.isArray( name ) ) {\r\n\r\n\t\t\t\t\tvar array = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, l = name.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar uuid = name[ i ];\r\n\r\n\t\t\t\t\t\tif ( materials[ uuid ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined material', uuid );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tarray.push( materials[ uuid ] );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn array;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( materials[ name ] === undefined ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader: Undefined material', name );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn materials[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tswitch ( data.type ) {\r\n\r\n\t\t\t\tcase 'Scene':\r\n\r\n\t\t\t\t\tobject = new Scene();\r\n\r\n\t\t\t\t\tif ( data.background !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( Number.isInteger( data.background ) ) {\r\n\r\n\t\t\t\t\t\t\tobject.background = new Color( data.background );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( data.fog !== undefined ) {\r\n\r\n\t\t\t\t\t\tif ( data.fog.type === 'Fog' ) {\r\n\r\n\t\t\t\t\t\t\tobject.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );\r\n\r\n\t\t\t\t\t\t} else if ( data.fog.type === 'FogExp2' ) {\r\n\r\n\t\t\t\t\t\t\tobject.fog = new FogExp2( data.fog.color, data.fog.density );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PerspectiveCamera':\r\n\r\n\t\t\t\t\tobject = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );\r\n\r\n\t\t\t\t\tif ( data.focus !== undefined ) { object.focus = data.focus; }\r\n\t\t\t\t\tif ( data.zoom !== undefined ) { object.zoom = data.zoom; }\r\n\t\t\t\t\tif ( data.filmGauge !== undefined ) { object.filmGauge = data.filmGauge; }\r\n\t\t\t\t\tif ( data.filmOffset !== undefined ) { object.filmOffset = data.filmOffset; }\r\n\t\t\t\t\tif ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); }\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'OrthographicCamera':\r\n\r\n\t\t\t\t\tobject = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );\r\n\r\n\t\t\t\t\tif ( data.zoom !== undefined ) { object.zoom = data.zoom; }\r\n\t\t\t\t\tif ( data.view !== undefined ) { object.view = Object.assign( {}, data.view ); }\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'AmbientLight':\r\n\r\n\t\t\t\t\tobject = new AmbientLight( data.color, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'DirectionalLight':\r\n\r\n\t\t\t\t\tobject = new DirectionalLight( data.color, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PointLight':\r\n\r\n\t\t\t\t\tobject = new PointLight( data.color, data.intensity, data.distance, data.decay );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'RectAreaLight':\r\n\r\n\t\t\t\t\tobject = new RectAreaLight( data.color, data.intensity, data.width, data.height );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'SpotLight':\r\n\r\n\t\t\t\t\tobject = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'HemisphereLight':\r\n\r\n\t\t\t\t\tobject = new HemisphereLight( data.color, data.groundColor, data.intensity );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'SkinnedMesh':\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' );\r\n\r\n\t\t\t\tcase 'Mesh':\r\n\r\n\t\t\t\t\tvar geometry = getGeometry( data.geometry );\r\n\t\t\t\t\tvar material = getMaterial( data.material );\r\n\r\n\t\t\t\t\tif ( geometry.bones && geometry.bones.length > 0 ) {\r\n\r\n\t\t\t\t\t\tobject = new SkinnedMesh( geometry, material );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tobject = new Mesh( geometry, material );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'InstancedMesh':\r\n\r\n\t\t\t\t\tvar geometry = getGeometry( data.geometry );\r\n\t\t\t\t\tvar material = getMaterial( data.material );\r\n\t\t\t\t\tvar count = data.count;\r\n\t\t\t\t\tvar instanceMatrix = data.instanceMatrix;\r\n\r\n\t\t\t\t\tobject = new InstancedMesh( geometry, material, count );\r\n\t\t\t\t\tobject.instanceMatrix = new BufferAttribute( new Float32Array( instanceMatrix.array ), 16 );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LOD':\r\n\r\n\t\t\t\t\tobject = new LOD();\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Line':\r\n\r\n\t\t\t\t\tobject = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LineLoop':\r\n\r\n\t\t\t\t\tobject = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'LineSegments':\r\n\r\n\t\t\t\t\tobject = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'PointCloud':\r\n\t\t\t\tcase 'Points':\r\n\r\n\t\t\t\t\tobject = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Sprite':\r\n\r\n\t\t\t\t\tobject = new Sprite( getMaterial( data.material ) );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'Group':\r\n\r\n\t\t\t\t\tobject = new Group();\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\r\n\t\t\t\t\tobject = new Object3D();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tobject.uuid = data.uuid;\r\n\r\n\t\t\tif ( data.name !== undefined ) { object.name = data.name; }\r\n\r\n\t\t\tif ( data.matrix !== undefined ) {\r\n\r\n\t\t\t\tobject.matrix.fromArray( data.matrix );\r\n\r\n\t\t\t\tif ( data.matrixAutoUpdate !== undefined ) { object.matrixAutoUpdate = data.matrixAutoUpdate; }\r\n\t\t\t\tif ( object.matrixAutoUpdate ) { object.matrix.decompose( object.position, object.quaternion, object.scale ); }\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( data.position !== undefined ) { object.position.fromArray( data.position ); }\r\n\t\t\t\tif ( data.rotation !== undefined ) { object.rotation.fromArray( data.rotation ); }\r\n\t\t\t\tif ( data.quaternion !== undefined ) { object.quaternion.fromArray( data.quaternion ); }\r\n\t\t\t\tif ( data.scale !== undefined ) { object.scale.fromArray( data.scale ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.castShadow !== undefined ) { object.castShadow = data.castShadow; }\r\n\t\t\tif ( data.receiveShadow !== undefined ) { object.receiveShadow = data.receiveShadow; }\r\n\r\n\t\t\tif ( data.shadow ) {\r\n\r\n\t\t\t\tif ( data.shadow.bias !== undefined ) { object.shadow.bias = data.shadow.bias; }\r\n\t\t\t\tif ( data.shadow.radius !== undefined ) { object.shadow.radius = data.shadow.radius; }\r\n\t\t\t\tif ( data.shadow.mapSize !== undefined ) { object.shadow.mapSize.fromArray( data.shadow.mapSize ); }\r\n\t\t\t\tif ( data.shadow.camera !== undefined ) { object.shadow.camera = this.parseObject( data.shadow.camera ); }\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.visible !== undefined ) { object.visible = data.visible; }\r\n\t\t\tif ( data.frustumCulled !== undefined ) { object.frustumCulled = data.frustumCulled; }\r\n\t\t\tif ( data.renderOrder !== undefined ) { object.renderOrder = data.renderOrder; }\r\n\t\t\tif ( data.userData !== undefined ) { object.userData = data.userData; }\r\n\t\t\tif ( data.layers !== undefined ) { object.layers.mask = data.layers; }\r\n\r\n\t\t\tif ( data.children !== undefined ) {\r\n\r\n\t\t\t\tvar children = data.children;\r\n\r\n\t\t\t\tfor ( var i = 0; i < children.length; i ++ ) {\r\n\r\n\t\t\t\t\tobject.add( this.parseObject( children[ i ], geometries, materials ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( data.type === 'LOD' ) {\r\n\r\n\t\t\t\tif ( data.autoUpdate !== undefined ) { object.autoUpdate = data.autoUpdate; }\r\n\r\n\t\t\t\tvar levels = data.levels;\r\n\r\n\t\t\t\tfor ( var l = 0; l < levels.length; l ++ ) {\r\n\r\n\t\t\t\t\tvar level = levels[ l ];\r\n\t\t\t\t\tvar child = object.getObjectByProperty( 'uuid', level.object );\r\n\r\n\t\t\t\t\tif ( child !== undefined ) {\r\n\r\n\t\t\t\t\t\tobject.addLevel( child, level.distance );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn object;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tvar TEXTURE_MAPPING = {\r\n\t\tUVMapping: UVMapping,\r\n\t\tCubeReflectionMapping: CubeReflectionMapping,\r\n\t\tCubeRefractionMapping: CubeRefractionMapping,\r\n\t\tEquirectangularReflectionMapping: EquirectangularReflectionMapping,\r\n\t\tEquirectangularRefractionMapping: EquirectangularRefractionMapping,\r\n\t\tSphericalReflectionMapping: SphericalReflectionMapping,\r\n\t\tCubeUVReflectionMapping: CubeUVReflectionMapping,\r\n\t\tCubeUVRefractionMapping: CubeUVRefractionMapping\r\n\t};\r\n\r\n\tvar TEXTURE_WRAPPING = {\r\n\t\tRepeatWrapping: RepeatWrapping,\r\n\t\tClampToEdgeWrapping: ClampToEdgeWrapping,\r\n\t\tMirroredRepeatWrapping: MirroredRepeatWrapping\r\n\t};\r\n\r\n\tvar TEXTURE_FILTER = {\r\n\t\tNearestFilter: NearestFilter,\r\n\t\tNearestMipmapNearestFilter: NearestMipmapNearestFilter,\r\n\t\tNearestMipmapLinearFilter: NearestMipmapLinearFilter,\r\n\t\tLinearFilter: LinearFilter,\r\n\t\tLinearMipmapNearestFilter: LinearMipmapNearestFilter,\r\n\t\tLinearMipmapLinearFilter: LinearMipmapLinearFilter\r\n\t};\n\n\t/**\r\n\t * @author thespite / http://clicktorelease.com/\r\n\t */\r\n\r\n\r\n\tfunction ImageBitmapLoader( manager ) {\r\n\r\n\t\tif ( typeof createImageBitmap === 'undefined' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( typeof fetch === 'undefined' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );\r\n\r\n\t\t}\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t\tthis.options = undefined;\r\n\r\n\t}\r\n\r\n\tImageBitmapLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: ImageBitmapLoader,\r\n\r\n\t\tsetOptions: function setOptions( options ) {\r\n\r\n\t\t\tthis.options = options;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tif ( url === undefined ) { url = ''; }\r\n\r\n\t\t\tif ( this.path !== undefined ) { url = this.path + url; }\r\n\r\n\t\t\turl = this.manager.resolveURL( url );\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar cached = Cache.get( url );\r\n\r\n\t\t\tif ( cached !== undefined ) {\r\n\r\n\t\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\t\tsetTimeout( function () {\r\n\r\n\t\t\t\t\tif ( onLoad ) { onLoad( cached ); }\r\n\r\n\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t}, 0 );\r\n\r\n\t\t\t\treturn cached;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfetch( url ).then( function ( res ) {\r\n\r\n\t\t\t\treturn res.blob();\r\n\r\n\t\t\t} ).then( function ( blob ) {\r\n\r\n\t\t\t\tif ( scope.options === undefined ) {\r\n\r\n\t\t\t\t\t// Workaround for FireFox. It causes an error if you pass options.\r\n\t\t\t\t\treturn createImageBitmap( blob );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\treturn createImageBitmap( blob, scope.options );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} ).then( function ( imageBitmap ) {\r\n\r\n\t\t\t\tCache.add( url, imageBitmap );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( imageBitmap ); }\r\n\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t} ).catch( function ( e ) {\r\n\r\n\t\t\t\tif ( onError ) { onError( e ); }\r\n\r\n\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * minimal class for proxing functions to Path. Replaces old \"extractSubpaths()\"\r\n\t **/\r\n\r\n\tfunction ShapePath() {\r\n\r\n\t\tthis.type = 'ShapePath';\r\n\r\n\t\tthis.color = new Color();\r\n\r\n\t\tthis.subPaths = [];\r\n\t\tthis.currentPath = null;\r\n\r\n\t}\r\n\r\n\tObject.assign( ShapePath.prototype, {\r\n\r\n\t\tmoveTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPath = new Path();\r\n\t\t\tthis.subPaths.push( this.currentPath );\r\n\t\t\tthis.currentPath.moveTo( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlineTo: function ( x, y ) {\r\n\r\n\t\t\tthis.currentPath.lineTo( x, y );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tquadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {\r\n\r\n\t\t\tthis.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tbezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {\r\n\r\n\t\t\tthis.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsplineThru: function ( pts ) {\r\n\r\n\t\t\tthis.currentPath.splineThru( pts );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoShapes: function ( isCCW, noHoles ) {\r\n\r\n\t\t\tfunction toShapesNoHoles( inSubpaths ) {\r\n\r\n\t\t\t\tvar shapes = [];\r\n\r\n\t\t\t\tfor ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tvar tmpPath = inSubpaths[ i ];\r\n\r\n\t\t\t\t\tvar tmpShape = new Shape();\r\n\t\t\t\t\ttmpShape.curves = tmpPath.curves;\r\n\r\n\t\t\t\t\tshapes.push( tmpShape );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn shapes;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfunction isPointInsidePolygon( inPt, inPolygon ) {\r\n\r\n\t\t\t\tvar polyLen = inPolygon.length;\r\n\r\n\t\t\t\t// inPt on polygon contour => immediate success or\r\n\t\t\t\t// toggling of inside/outside at every single! intersection point of an edge\r\n\t\t\t\t// with the horizontal line through inPt, left of inPt\r\n\t\t\t\t// not counting lowerY endpoints of edges and whole edges on that line\r\n\t\t\t\tvar inside = false;\r\n\t\t\t\tfor ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {\r\n\r\n\t\t\t\t\tvar edgeLowPt = inPolygon[ p ];\r\n\t\t\t\t\tvar edgeHighPt = inPolygon[ q ];\r\n\r\n\t\t\t\t\tvar edgeDx = edgeHighPt.x - edgeLowPt.x;\r\n\t\t\t\t\tvar edgeDy = edgeHighPt.y - edgeLowPt.y;\r\n\r\n\t\t\t\t\tif ( Math.abs( edgeDy ) > Number.EPSILON ) {\r\n\r\n\t\t\t\t\t\t// not parallel\r\n\t\t\t\t\t\tif ( edgeDy < 0 ) {\r\n\r\n\t\t\t\t\t\t\tedgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;\r\n\t\t\t\t\t\t\tedgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) \t\t{ continue; }\r\n\r\n\t\t\t\t\t\tif ( inPt.y === edgeLowPt.y ) {\r\n\r\n\t\t\t\t\t\t\tif ( inPt.x === edgeLowPt.x )\t\t{ return\ttrue; }\t\t// inPt is on contour ?\r\n\t\t\t\t\t\t\t// continue;\t\t\t\t// no intersection or edgeLowPt => doesn't count !!!\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tvar perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );\r\n\t\t\t\t\t\t\tif ( perpEdge === 0 )\t\t\t\t{ return\ttrue; }\t\t// inPt is on contour ?\r\n\t\t\t\t\t\t\tif ( perpEdge < 0 ) \t\t\t\t{ continue; }\r\n\t\t\t\t\t\t\tinside = ! inside;\t\t// true intersection left of inPt\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// parallel or collinear\r\n\t\t\t\t\t\tif ( inPt.y !== edgeLowPt.y ) \t\t{ continue; }\t\t\t// parallel\r\n\t\t\t\t\t\t// edge lies on the same horizontal line as inPt\r\n\t\t\t\t\t\tif ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||\r\n\t\t\t\t\t\t\t ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) )\t\t{ return\ttrue; }\t// inPt: Point on contour !\r\n\t\t\t\t\t\t// continue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn\tinside;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar isClockWise = ShapeUtils.isClockWise;\r\n\r\n\t\t\tvar subPaths = this.subPaths;\r\n\t\t\tif ( subPaths.length === 0 ) { return []; }\r\n\r\n\t\t\tif ( noHoles === true )\t{ return\ttoShapesNoHoles( subPaths ); }\r\n\r\n\r\n\t\t\tvar solid, tmpPath, tmpShape, shapes = [];\r\n\r\n\t\t\tif ( subPaths.length === 1 ) {\r\n\r\n\t\t\t\ttmpPath = subPaths[ 0 ];\r\n\t\t\t\ttmpShape = new Shape();\r\n\t\t\t\ttmpShape.curves = tmpPath.curves;\r\n\t\t\t\tshapes.push( tmpShape );\r\n\t\t\t\treturn shapes;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );\r\n\t\t\tholesFirst = isCCW ? ! holesFirst : holesFirst;\r\n\r\n\t\t\t// console.log(\"Holes first\", holesFirst);\r\n\r\n\t\t\tvar betterShapeHoles = [];\r\n\t\t\tvar newShapes = [];\r\n\t\t\tvar newShapeHoles = [];\r\n\t\t\tvar mainIdx = 0;\r\n\t\t\tvar tmpPoints;\r\n\r\n\t\t\tnewShapes[ mainIdx ] = undefined;\r\n\t\t\tnewShapeHoles[ mainIdx ] = [];\r\n\r\n\t\t\tfor ( var i = 0, l = subPaths.length; i < l; i ++ ) {\r\n\r\n\t\t\t\ttmpPath = subPaths[ i ];\r\n\t\t\t\ttmpPoints = tmpPath.getPoints();\r\n\t\t\t\tsolid = isClockWise( tmpPoints );\r\n\t\t\t\tsolid = isCCW ? ! solid : solid;\r\n\r\n\t\t\t\tif ( solid ) {\r\n\r\n\t\t\t\t\tif ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) )\t{ mainIdx ++; }\r\n\r\n\t\t\t\t\tnewShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };\r\n\t\t\t\t\tnewShapes[ mainIdx ].s.curves = tmpPath.curves;\r\n\r\n\t\t\t\t\tif ( holesFirst )\t{ mainIdx ++; }\r\n\t\t\t\t\tnewShapeHoles[ mainIdx ] = [];\r\n\r\n\t\t\t\t\t//console.log('cw', i);\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tnewShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );\r\n\r\n\t\t\t\t\t//console.log('ccw', i);\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// only Holes? -> probably all Shapes with wrong orientation\r\n\t\t\tif ( ! newShapes[ 0 ] )\t{ return\ttoShapesNoHoles( subPaths ); }\r\n\r\n\r\n\t\t\tif ( newShapes.length > 1 ) {\r\n\r\n\t\t\t\tvar ambiguous = false;\r\n\t\t\t\tvar toChange = [];\r\n\r\n\t\t\t\tfor ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {\r\n\r\n\t\t\t\t\tbetterShapeHoles[ sIdx ] = [];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {\r\n\r\n\t\t\t\t\tvar sho = newShapeHoles[ sIdx ];\r\n\r\n\t\t\t\t\tfor ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {\r\n\r\n\t\t\t\t\t\tvar ho = sho[ hIdx ];\r\n\t\t\t\t\t\tvar hole_unassigned = true;\r\n\r\n\t\t\t\t\t\tfor ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {\r\n\r\n\t\t\t\t\t\t\t\tif ( sIdx !== s2Idx )\t{ toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); }\r\n\t\t\t\t\t\t\t\tif ( hole_unassigned ) {\r\n\r\n\t\t\t\t\t\t\t\t\thole_unassigned = false;\r\n\t\t\t\t\t\t\t\t\tbetterShapeHoles[ s2Idx ].push( ho );\r\n\r\n\t\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\t\tambiguous = true;\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif ( hole_unassigned ) {\r\n\r\n\t\t\t\t\t\t\tbetterShapeHoles[ sIdx ].push( ho );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\t\t\t\t// console.log(\"ambiguous: \", ambiguous);\r\n\t\t\t\tif ( toChange.length > 0 ) {\r\n\r\n\t\t\t\t\t// console.log(\"to change: \", toChange);\r\n\t\t\t\t\tif ( ! ambiguous )\t{ newShapeHoles = betterShapeHoles; }\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar tmpHoles;\r\n\r\n\t\t\tfor ( var i = 0, il = newShapes.length; i < il; i ++ ) {\r\n\r\n\t\t\t\ttmpShape = newShapes[ i ].s;\r\n\t\t\t\tshapes.push( tmpShape );\r\n\t\t\t\ttmpHoles = newShapeHoles[ i ];\r\n\r\n\t\t\t\tfor ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\ttmpShape.holes.push( tmpHoles[ j ].h );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t//console.log(\"shape\", shapes);\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author zz85 / http://www.lab4games.net/zz85/blog\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\r\n\tfunction Font( data ) {\r\n\r\n\t\tthis.type = 'Font';\r\n\r\n\t\tthis.data = data;\r\n\r\n\t}\r\n\r\n\tObject.assign( Font.prototype, {\r\n\r\n\t\tisFont: true,\r\n\r\n\t\tgenerateShapes: function ( text, size ) {\r\n\r\n\t\t\tif ( size === undefined ) { size = 100; }\r\n\r\n\t\t\tvar shapes = [];\r\n\t\t\tvar paths = createPaths( text, size, this.data );\r\n\r\n\t\t\tfor ( var p = 0, pl = paths.length; p < pl; p ++ ) {\r\n\r\n\t\t\t\tArray.prototype.push.apply( shapes, paths[ p ].toShapes() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn shapes;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tfunction createPaths( text, size, data ) {\r\n\r\n\t\tvar chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // see #13988\r\n\t\tvar scale = size / data.resolution;\r\n\t\tvar line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale;\r\n\r\n\t\tvar paths = [];\r\n\r\n\t\tvar offsetX = 0, offsetY = 0;\r\n\r\n\t\tfor ( var i = 0; i < chars.length; i ++ ) {\r\n\r\n\t\t\tvar char = chars[ i ];\r\n\r\n\t\t\tif ( char === '\\n' ) {\r\n\r\n\t\t\t\toffsetX = 0;\r\n\t\t\t\toffsetY -= line_height;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar ret = createPath( char, scale, offsetX, offsetY, data );\r\n\t\t\t\toffsetX += ret.offsetX;\r\n\t\t\t\tpaths.push( ret.path );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn paths;\r\n\r\n\t}\r\n\r\n\tfunction createPath( char, scale, offsetX, offsetY, data ) {\r\n\r\n\t\tvar glyph = data.glyphs[ char ] || data.glyphs[ '?' ];\r\n\r\n\t\tif ( ! glyph ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Font: character \"' + char + '\" does not exists in font family ' + data.familyName + '.' );\r\n\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tvar path = new ShapePath();\r\n\r\n\t\tvar x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2;\r\n\r\n\t\tif ( glyph.o ) {\r\n\r\n\t\t\tvar outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );\r\n\r\n\t\t\tfor ( var i = 0, l = outline.length; i < l; ) {\r\n\r\n\t\t\t\tvar action = outline[ i ++ ];\r\n\r\n\t\t\t\tswitch ( action ) {\r\n\r\n\t\t\t\t\tcase 'm': // moveTo\r\n\r\n\t\t\t\t\t\tx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\ty = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.moveTo( x, y );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'l': // lineTo\r\n\r\n\t\t\t\t\t\tx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\ty = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.lineTo( x, y );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'q': // quadraticCurveTo\r\n\r\n\t\t\t\t\t\tcpx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx1 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy1 = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.quadraticCurveTo( cpx1, cpy1, cpx, cpy );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'b': // bezierCurveTo\r\n\r\n\t\t\t\t\t\tcpx = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx1 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy1 = outline[ i ++ ] * scale + offsetY;\r\n\t\t\t\t\t\tcpx2 = outline[ i ++ ] * scale + offsetX;\r\n\t\t\t\t\t\tcpy2 = outline[ i ++ ] * scale + offsetY;\r\n\r\n\t\t\t\t\t\tpath.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy );\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn { offsetX: glyph.ha * scale, path: path };\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction FontLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tFontLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: FontLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\t\tvar json;\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tjson = JSON.parse( text );\r\n\r\n\t\t\t\t} catch ( e ) {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' );\r\n\t\t\t\t\tjson = JSON.parse( text.substring( 65, text.length - 2 ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar font = scope.parse( json );\r\n\r\n\t\t\t\tif ( onLoad ) { onLoad( font ); }\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( json ) {\r\n\r\n\t\t\treturn new Font( json );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _context;\r\n\r\n\tvar AudioContext = {\r\n\r\n\t\tgetContext: function () {\r\n\r\n\t\t\tif ( _context === undefined ) {\r\n\r\n\t\t\t\t_context = new ( window.AudioContext || window.webkitAudioContext )();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn _context;\r\n\r\n\t\t},\r\n\r\n\t\tsetContext: function ( value ) {\r\n\r\n\t\t\t_context = value;\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author Reece Aaron Lecrivain / http://reecenotes.com/\r\n\t */\r\n\r\n\tfunction AudioLoader( manager ) {\r\n\r\n\t\tLoader.call( this, manager );\r\n\r\n\t}\r\n\r\n\tAudioLoader.prototype = Object.assign( Object.create( Loader.prototype ), {\r\n\r\n\t\tconstructor: AudioLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar loader = new FileLoader( this.manager );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.load( url, function ( buffer ) {\r\n\r\n\t\t\t\t// Create a copy of the buffer. The `decodeAudioData` method\r\n\t\t\t\t// detaches the buffer when complete, preventing reuse.\r\n\t\t\t\tvar bufferCopy = buffer.slice( 0 );\r\n\r\n\t\t\t\tvar context = AudioContext.getContext();\r\n\t\t\t\tcontext.decodeAudioData( bufferCopy, function ( audioBuffer ) {\r\n\r\n\t\t\t\t\tonLoad( audioBuffer );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}, onProgress, onError );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * Primary reference:\r\n\t * https://graphics.stanford.edu/papers/envmap/envmap.pdf\r\n\t *\r\n\t * Secondary reference:\r\n\t * https://www.ppsloan.org/publications/StupidSH36.pdf\r\n\t */\r\n\r\n\t// 3-band SH defined by 9 coefficients\r\n\r\n\tfunction SphericalHarmonics3() {\r\n\r\n\t\tthis.coefficients = [];\r\n\r\n\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\tthis.coefficients.push( new Vector3() );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( SphericalHarmonics3.prototype, {\r\n\r\n\t\tisSphericalHarmonics3: true,\r\n\r\n\t\tset: function ( coefficients ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].copy( coefficients[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tzero: function () {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].set( 0, 0, 0 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// get the radiance in the direction of the normal\r\n\t\t// target is a Vector3\r\n\t\tgetAt: function ( normal, target ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\tvar coeff = this.coefficients;\r\n\r\n\t\t\t// band 0\r\n\t\t\ttarget.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );\r\n\r\n\t\t\t// band 1\r\n\t\t\ttarget.addScale( coeff[ 1 ], 0.488603 * y );\r\n\t\t\ttarget.addScale( coeff[ 2 ], 0.488603 * z );\r\n\t\t\ttarget.addScale( coeff[ 3 ], 0.488603 * x );\r\n\r\n\t\t\t// band 2\r\n\t\t\ttarget.addScale( coeff[ 4 ], 1.092548 * ( x * y ) );\r\n\t\t\ttarget.addScale( coeff[ 5 ], 1.092548 * ( y * z ) );\r\n\t\t\ttarget.addScale( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );\r\n\t\t\ttarget.addScale( coeff[ 7 ], 1.092548 * ( x * z ) );\r\n\t\t\ttarget.addScale( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\t// get the irradiance (radiance convolved with cosine lobe) in the direction of the normal\r\n\t\t// target is a Vector3\r\n\t\t// https://graphics.stanford.edu/papers/envmap/envmap.pdf\r\n\t\tgetIrradianceAt: function ( normal, target ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\tvar coeff = this.coefficients;\r\n\r\n\t\t\t// band 0\r\n\t\t\ttarget.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095\r\n\r\n\t\t\t// band 1\r\n\t\t\ttarget.addScale( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603\r\n\t\t\ttarget.addScale( coeff[ 2 ], 2.0 * 0.511664 * z );\r\n\t\t\ttarget.addScale( coeff[ 3 ], 2.0 * 0.511664 * x );\r\n\r\n\t\t\t// band 2\r\n\t\t\ttarget.addScale( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548\r\n\t\t\ttarget.addScale( coeff[ 5 ], 2.0 * 0.429043 * y * z );\r\n\t\t\ttarget.addScale( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3\r\n\t\t\ttarget.addScale( coeff[ 7 ], 2.0 * 0.429043 * x * z );\r\n\t\t\ttarget.addScale( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274\r\n\r\n\t\t\treturn target;\r\n\r\n\t\t},\r\n\r\n\t\tadd: function ( sh ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].add( sh.coefficients[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\r\n\t\tscale: function ( s ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].multiplyScalar( s );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tlerp: function ( sh, alpha ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tthis.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( sh ) {\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tif ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {\r\n\r\n\t\t\t\t\treturn false;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn true;\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( sh ) {\r\n\r\n\t\t\treturn this.set( sh.coefficients );\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tfromArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar coefficients = this.coefficients;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tcoefficients[ i ].fromArray( array, offset + ( i * 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoArray: function ( array, offset ) {\r\n\r\n\t\t\tif ( array === undefined ) { array = []; }\r\n\t\t\tif ( offset === undefined ) { offset = 0; }\r\n\r\n\t\t\tvar coefficients = this.coefficients;\r\n\r\n\t\t\tfor ( var i = 0; i < 9; i ++ ) {\r\n\r\n\t\t\t\tcoefficients[ i ].toArray( array, offset + ( i * 3 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn array;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( SphericalHarmonics3, {\r\n\r\n\t\t// evaluate the basis functions\r\n\t\t// shBasis is an Array[ 9 ]\r\n\t\tgetBasisAt: function ( normal, shBasis ) {\r\n\r\n\t\t\t// normal is assumed to be unit length\r\n\r\n\t\t\tvar x = normal.x, y = normal.y, z = normal.z;\r\n\r\n\t\t\t// band 0\r\n\t\t\tshBasis[ 0 ] = 0.282095;\r\n\r\n\t\t\t// band 1\r\n\t\t\tshBasis[ 1 ] = 0.488603 * y;\r\n\t\t\tshBasis[ 2 ] = 0.488603 * z;\r\n\t\t\tshBasis[ 3 ] = 0.488603 * x;\r\n\r\n\t\t\t// band 2\r\n\t\t\tshBasis[ 4 ] = 1.092548 * x * y;\r\n\t\t\tshBasis[ 5 ] = 1.092548 * y * z;\r\n\t\t\tshBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );\r\n\t\t\tshBasis[ 7 ] = 1.092548 * x * z;\r\n\t\t\tshBasis[ 8 ] = 0.546274 * ( x * x - y * y );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * A LightProbe is a source of indirect-diffuse light\r\n\t */\r\n\r\n\tfunction LightProbe( sh, intensity ) {\r\n\r\n\t\tLight.call( this, undefined, intensity );\r\n\r\n\t\tthis.sh = ( sh !== undefined ) ? sh : new SphericalHarmonics3();\r\n\r\n\t}\r\n\r\n\tLightProbe.prototype = Object.assign( Object.create( Light.prototype ), {\r\n\r\n\t\tconstructor: LightProbe,\r\n\r\n\t\tisLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLight.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.sh.copy( source.sh );\r\n\t\t\tthis.intensity = source.intensity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = Light.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction HemisphereLightProbe( skyColor, groundColor, intensity ) {\r\n\r\n\t\tLightProbe.call( this, undefined, intensity );\r\n\r\n\t\tvar color1 = new Color().set( skyColor );\r\n\t\tvar color2 = new Color().set( groundColor );\r\n\r\n\t\tvar sky = new Vector3( color1.r, color1.g, color1.b );\r\n\t\tvar ground = new Vector3( color2.r, color2.g, color2.b );\r\n\r\n\t\t// without extra factor of PI in the shader, should = 1 / Math.sqrt( Math.PI );\r\n\t\tvar c0 = Math.sqrt( Math.PI );\r\n\t\tvar c1 = c0 * Math.sqrt( 0.75 );\r\n\r\n\t\tthis.sh.coefficients[ 0 ].copy( sky ).add( ground ).multiplyScalar( c0 );\r\n\t\tthis.sh.coefficients[ 1 ].copy( sky ).sub( ground ).multiplyScalar( c1 );\r\n\r\n\t}\r\n\r\n\tHemisphereLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {\r\n\r\n\t\tconstructor: HemisphereLightProbe,\r\n\r\n\t\tisHemisphereLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) { // modifying colors not currently supported\r\n\r\n\t\t\tLightProbe.prototype.copy.call( this, source );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = LightProbe.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction AmbientLightProbe( color, intensity ) {\r\n\r\n\t\tLightProbe.call( this, undefined, intensity );\r\n\r\n\t\tvar color1 = new Color().set( color );\r\n\r\n\t\t// without extra factor of PI in the shader, would be 2 / Math.sqrt( Math.PI );\r\n\t\tthis.sh.coefficients[ 0 ].set( color1.r, color1.g, color1.b ).multiplyScalar( 2 * Math.sqrt( Math.PI ) );\r\n\r\n\t}\r\n\r\n\tAmbientLightProbe.prototype = Object.assign( Object.create( LightProbe.prototype ), {\r\n\r\n\t\tconstructor: AmbientLightProbe,\r\n\r\n\t\tisAmbientLightProbe: true,\r\n\r\n\t\tcopy: function ( source ) { // modifying color not currently supported\r\n\r\n\t\t\tLightProbe.prototype.copy.call( this, source );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttoJSON: function ( meta ) {\r\n\r\n\t\t\tvar data = LightProbe.prototype.toJSON.call( this, meta );\r\n\r\n\t\t\t// data.sh = this.sh.toArray(); // todo\r\n\r\n\t\t\treturn data;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\tvar _eyeRight = new Matrix4();\r\n\tvar _eyeLeft = new Matrix4();\r\n\r\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction StereoCamera() {\r\n\r\n\t\tthis.type = 'StereoCamera';\r\n\r\n\t\tthis.aspect = 1;\r\n\r\n\t\tthis.eyeSep = 0.064;\r\n\r\n\t\tthis.cameraL = new PerspectiveCamera();\r\n\t\tthis.cameraL.layers.enable( 1 );\r\n\t\tthis.cameraL.matrixAutoUpdate = false;\r\n\r\n\t\tthis.cameraR = new PerspectiveCamera();\r\n\t\tthis.cameraR.layers.enable( 2 );\r\n\t\tthis.cameraR.matrixAutoUpdate = false;\r\n\r\n\t\tthis._cache = {\r\n\t\t\tfocus: null,\r\n\t\t\tfov: null,\r\n\t\t\taspect: null,\r\n\t\t\tnear: null,\r\n\t\t\tfar: null,\r\n\t\t\tzoom: null,\r\n\t\t\teyeSep: null\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( StereoCamera.prototype, {\r\n\r\n\t\tupdate: function ( camera ) {\r\n\r\n\t\t\tvar cache = this._cache;\r\n\r\n\t\t\tvar needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||\r\n\t\t\t\tcache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||\r\n\t\t\t\tcache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;\r\n\r\n\t\t\tif ( needsUpdate ) {\r\n\r\n\t\t\t\tcache.focus = camera.focus;\r\n\t\t\t\tcache.fov = camera.fov;\r\n\t\t\t\tcache.aspect = camera.aspect * this.aspect;\r\n\t\t\t\tcache.near = camera.near;\r\n\t\t\t\tcache.far = camera.far;\r\n\t\t\t\tcache.zoom = camera.zoom;\r\n\t\t\t\tcache.eyeSep = this.eyeSep;\r\n\r\n\t\t\t\t// Off-axis stereoscopic effect based on\r\n\t\t\t\t// http://paulbourke.net/stereographics/stereorender/\r\n\r\n\t\t\t\tvar projectionMatrix = camera.projectionMatrix.clone();\r\n\t\t\t\tvar eyeSepHalf = cache.eyeSep / 2;\r\n\t\t\t\tvar eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;\r\n\t\t\t\tvar ymax = ( cache.near * Math.tan( _Math.DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;\r\n\t\t\t\tvar xmin, xmax;\r\n\r\n\t\t\t\t// translate xOffset\r\n\r\n\t\t\t\t_eyeLeft.elements[ 12 ] = - eyeSepHalf;\r\n\t\t\t\t_eyeRight.elements[ 12 ] = eyeSepHalf;\r\n\r\n\t\t\t\t// for left eye\r\n\r\n\t\t\t\txmin = - ymax * cache.aspect + eyeSepOnProjection;\r\n\t\t\t\txmax = ymax * cache.aspect + eyeSepOnProjection;\r\n\r\n\t\t\t\tprojectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );\r\n\t\t\t\tprojectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );\r\n\r\n\t\t\t\tthis.cameraL.projectionMatrix.copy( projectionMatrix );\r\n\r\n\t\t\t\t// for right eye\r\n\r\n\t\t\t\txmin = - ymax * cache.aspect - eyeSepOnProjection;\r\n\t\t\t\txmax = ymax * cache.aspect - eyeSepOnProjection;\r\n\r\n\t\t\t\tprojectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );\r\n\t\t\t\tprojectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );\r\n\r\n\t\t\t\tthis.cameraR.projectionMatrix.copy( projectionMatrix );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );\r\n\t\t\tthis.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction Clock( autoStart ) {\r\n\r\n\t\tthis.autoStart = ( autoStart !== undefined ) ? autoStart : true;\r\n\r\n\t\tthis.startTime = 0;\r\n\t\tthis.oldTime = 0;\r\n\t\tthis.elapsedTime = 0;\r\n\r\n\t\tthis.running = false;\r\n\r\n\t}\r\n\r\n\tObject.assign( Clock.prototype, {\r\n\r\n\t\tstart: function () {\r\n\r\n\t\t\tthis.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732\r\n\r\n\t\t\tthis.oldTime = this.startTime;\r\n\t\t\tthis.elapsedTime = 0;\r\n\t\t\tthis.running = true;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tthis.getElapsedTime();\r\n\t\t\tthis.running = false;\r\n\t\t\tthis.autoStart = false;\r\n\r\n\t\t},\r\n\r\n\t\tgetElapsedTime: function () {\r\n\r\n\t\t\tthis.getDelta();\r\n\t\t\treturn this.elapsedTime;\r\n\r\n\t\t},\r\n\r\n\t\tgetDelta: function () {\r\n\r\n\t\t\tvar diff = 0;\r\n\r\n\t\t\tif ( this.autoStart && ! this.running ) {\r\n\r\n\t\t\t\tthis.start();\r\n\t\t\t\treturn 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.running ) {\r\n\r\n\t\t\t\tvar newTime = ( typeof performance === 'undefined' ? Date : performance ).now();\r\n\r\n\t\t\t\tdiff = ( newTime - this.oldTime ) / 1000;\r\n\t\t\t\tthis.oldTime = newTime;\r\n\r\n\t\t\t\tthis.elapsedTime += diff;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn diff;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _position$2 = new Vector3();\r\n\tvar _quaternion$3 = new Quaternion();\r\n\tvar _scale$1 = new Vector3();\r\n\tvar _orientation = new Vector3();\r\n\r\n\tfunction AudioListener() {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'AudioListener';\r\n\r\n\t\tthis.context = AudioContext.getContext();\r\n\r\n\t\tthis.gain = this.context.createGain();\r\n\t\tthis.gain.connect( this.context.destination );\r\n\r\n\t\tthis.filter = null;\r\n\r\n\t\tthis.timeDelta = 0;\r\n\r\n\t\t// private\r\n\r\n\t\tthis._clock = new Clock();\r\n\r\n\t}\r\n\r\n\tAudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: AudioListener,\r\n\r\n\t\tgetInput: function () {\r\n\r\n\t\t\treturn this.gain;\r\n\r\n\t\t},\r\n\r\n\t\tremoveFilter: function ( ) {\r\n\r\n\t\t\tif ( this.filter !== null ) {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.filter );\r\n\t\t\t\tthis.filter.disconnect( this.context.destination );\r\n\t\t\t\tthis.gain.connect( this.context.destination );\r\n\t\t\t\tthis.filter = null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilter: function () {\r\n\r\n\t\t\treturn this.filter;\r\n\r\n\t\t},\r\n\r\n\t\tsetFilter: function ( value ) {\r\n\r\n\t\t\tif ( this.filter !== null ) {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.filter );\r\n\t\t\t\tthis.filter.disconnect( this.context.destination );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.gain.disconnect( this.context.destination );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.filter = value;\r\n\t\t\tthis.gain.connect( this.filter );\r\n\t\t\tthis.filter.connect( this.context.destination );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMasterVolume: function () {\r\n\r\n\t\t\treturn this.gain.gain.value;\r\n\r\n\t\t},\r\n\r\n\t\tsetMasterVolume: function ( value ) {\r\n\r\n\t\t\tthis.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tvar listener = this.context.listener;\r\n\t\t\tvar up = this.up;\r\n\r\n\t\t\tthis.timeDelta = this._clock.getDelta();\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position$2, _quaternion$3, _scale$1 );\r\n\r\n\t\t\t_orientation.set( 0, 0, - 1 ).applyQuaternion( _quaternion$3 );\r\n\r\n\t\t\tif ( listener.positionX ) {\r\n\r\n\t\t\t\t// code path for Chrome (see #14393)\r\n\r\n\t\t\t\tvar endTime = this.context.currentTime + this.timeDelta;\r\n\r\n\t\t\t\tlistener.positionX.linearRampToValueAtTime( _position$2.x, endTime );\r\n\t\t\t\tlistener.positionY.linearRampToValueAtTime( _position$2.y, endTime );\r\n\t\t\t\tlistener.positionZ.linearRampToValueAtTime( _position$2.z, endTime );\r\n\t\t\t\tlistener.forwardX.linearRampToValueAtTime( _orientation.x, endTime );\r\n\t\t\t\tlistener.forwardY.linearRampToValueAtTime( _orientation.y, endTime );\r\n\t\t\t\tlistener.forwardZ.linearRampToValueAtTime( _orientation.z, endTime );\r\n\t\t\t\tlistener.upX.linearRampToValueAtTime( up.x, endTime );\r\n\t\t\t\tlistener.upY.linearRampToValueAtTime( up.y, endTime );\r\n\t\t\t\tlistener.upZ.linearRampToValueAtTime( up.z, endTime );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tlistener.setPosition( _position$2.x, _position$2.y, _position$2.z );\r\n\t\t\t\tlistener.setOrientation( _orientation.x, _orientation.y, _orientation.z, up.x, up.y, up.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Reece Aaron Lecrivain / http://reecenotes.com/\r\n\t */\r\n\r\n\tfunction Audio( listener ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.type = 'Audio';\r\n\r\n\t\tthis.listener = listener;\r\n\t\tthis.context = listener.context;\r\n\r\n\t\tthis.gain = this.context.createGain();\r\n\t\tthis.gain.connect( listener.getInput() );\r\n\r\n\t\tthis.autoplay = false;\r\n\r\n\t\tthis.buffer = null;\r\n\t\tthis.detune = 0;\r\n\t\tthis.loop = false;\r\n\t\tthis.loopStart = 0;\r\n\t\tthis.loopEnd = 0;\r\n\t\tthis.offset = 0;\r\n\t\tthis.duration = undefined;\r\n\t\tthis.playbackRate = 1;\r\n\t\tthis.isPlaying = false;\r\n\t\tthis.hasPlaybackControl = true;\r\n\t\tthis.sourceType = 'empty';\r\n\r\n\t\tthis._startedAt = 0;\r\n\t\tthis._pausedAt = 0;\r\n\r\n\t\tthis.filters = [];\r\n\r\n\t}\r\n\r\n\tAudio.prototype = Object.assign( Object.create( Object3D.prototype ), {\r\n\r\n\t\tconstructor: Audio,\r\n\r\n\t\tgetOutput: function () {\r\n\r\n\t\t\treturn this.gain;\r\n\r\n\t\t},\r\n\r\n\t\tsetNodeSource: function ( audioNode ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'audioNode';\r\n\t\t\tthis.source = audioNode;\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMediaElementSource: function ( mediaElement ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'mediaNode';\r\n\t\t\tthis.source = this.context.createMediaElementSource( mediaElement );\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetMediaStreamSource: function ( mediaStream ) {\r\n\r\n\t\t\tthis.hasPlaybackControl = false;\r\n\t\t\tthis.sourceType = 'mediaStreamNode';\r\n\t\t\tthis.source = this.context.createMediaStreamSource( mediaStream );\r\n\t\t\tthis.connect();\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetBuffer: function ( audioBuffer ) {\r\n\r\n\t\t\tthis.buffer = audioBuffer;\r\n\t\t\tthis.sourceType = 'buffer';\r\n\r\n\t\t\tif ( this.autoplay ) { this.play(); }\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tplay: function ( delay ) {\r\n\r\n\t\t\tif ( delay === undefined ) { delay = 0; }\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: Audio is already playing.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._startedAt = this.context.currentTime + delay;\r\n\r\n\t\t\tvar source = this.context.createBufferSource();\r\n\t\t\tsource.buffer = this.buffer;\r\n\t\t\tsource.loop = this.loop;\r\n\t\t\tsource.loopStart = this.loopStart;\r\n\t\t\tsource.loopEnd = this.loopEnd;\r\n\t\t\tsource.onended = this.onEnded.bind( this );\r\n\t\t\tsource.start( this._startedAt, this._pausedAt + this.offset, this.duration );\r\n\r\n\t\t\tthis.isPlaying = true;\r\n\r\n\t\t\tthis.source = source;\r\n\r\n\t\t\tthis.setDetune( this.detune );\r\n\t\t\tthis.setPlaybackRate( this.playbackRate );\r\n\r\n\t\t\treturn this.connect();\r\n\r\n\t\t},\r\n\r\n\t\tpause: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis._pausedAt = ( this.context.currentTime - this._startedAt ) * this.playbackRate;\r\n\r\n\t\t\t\tthis.source.stop();\r\n\t\t\t\tthis.source.onended = null;\r\n\r\n\t\t\t\tthis.isPlaying = false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._pausedAt = 0;\r\n\r\n\t\t\tthis.source.stop();\r\n\t\t\tthis.source.onended = null;\r\n\t\t\tthis.isPlaying = false;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tconnect: function () {\r\n\r\n\t\t\tif ( this.filters.length > 0 ) {\r\n\r\n\t\t\t\tthis.source.connect( this.filters[ 0 ] );\r\n\r\n\t\t\t\tfor ( var i = 1, l = this.filters.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tthis.filters[ i - 1 ].connect( this.filters[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.filters[ this.filters.length - 1 ].connect( this.getOutput() );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.source.connect( this.getOutput() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tdisconnect: function () {\r\n\r\n\t\t\tif ( this.filters.length > 0 ) {\r\n\r\n\t\t\t\tthis.source.disconnect( this.filters[ 0 ] );\r\n\r\n\t\t\t\tfor ( var i = 1, l = this.filters.length; i < l; i ++ ) {\r\n\r\n\t\t\t\t\tthis.filters[ i - 1 ].disconnect( this.filters[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.source.disconnect( this.getOutput() );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilters: function () {\r\n\r\n\t\t\treturn this.filters;\r\n\r\n\t\t},\r\n\r\n\t\tsetFilters: function ( value ) {\r\n\r\n\t\t\tif ( ! value ) { value = []; }\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.disconnect();\r\n\t\t\t\tthis.filters = value;\r\n\t\t\t\tthis.connect();\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.filters = value;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetDetune: function ( value ) {\r\n\r\n\t\t\tthis.detune = value;\r\n\r\n\t\t\tif ( this.source.detune === undefined ) { return; } // only set detune when available\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetDetune: function () {\r\n\r\n\t\t\treturn this.detune;\r\n\r\n\t\t},\r\n\r\n\t\tgetFilter: function () {\r\n\r\n\t\t\treturn this.getFilters()[ 0 ];\r\n\r\n\t\t},\r\n\r\n\t\tsetFilter: function ( filter ) {\r\n\r\n\t\t\treturn this.setFilters( filter ? [ filter ] : [] );\r\n\r\n\t\t},\r\n\r\n\t\tsetPlaybackRate: function ( value ) {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.playbackRate = value;\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetPlaybackRate: function () {\r\n\r\n\t\t\treturn this.playbackRate;\r\n\r\n\t\t},\r\n\r\n\t\tonEnded: function () {\r\n\r\n\t\t\tthis.isPlaying = false;\r\n\r\n\t\t},\r\n\r\n\t\tgetLoop: function () {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.loop;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoop: function ( value ) {\r\n\r\n\t\t\tif ( this.hasPlaybackControl === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: this Audio has no playback control.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.loop = value;\r\n\r\n\t\t\tif ( this.isPlaying === true ) {\r\n\r\n\t\t\t\tthis.source.loop = this.loop;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoopStart: function ( value ) {\r\n\r\n\t\t\tthis.loopStart = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoopEnd: function ( value ) {\r\n\r\n\t\t\tthis.loopEnd = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetVolume: function () {\r\n\r\n\t\t\treturn this.gain.gain.value;\r\n\r\n\t\t},\r\n\r\n\t\tsetVolume: function ( value ) {\r\n\r\n\t\t\tthis.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tvar _position$3 = new Vector3();\r\n\tvar _quaternion$4 = new Quaternion();\r\n\tvar _scale$2 = new Vector3();\r\n\tvar _orientation$1 = new Vector3();\r\n\r\n\tfunction PositionalAudio( listener ) {\r\n\r\n\t\tAudio.call( this, listener );\r\n\r\n\t\tthis.panner = this.context.createPanner();\r\n\t\tthis.panner.panningModel = 'HRTF';\r\n\t\tthis.panner.connect( this.gain );\r\n\r\n\t}\r\n\r\n\tPositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), {\r\n\r\n\t\tconstructor: PositionalAudio,\r\n\r\n\t\tgetOutput: function () {\r\n\r\n\t\t\treturn this.panner;\r\n\r\n\t\t},\r\n\r\n\t\tgetRefDistance: function () {\r\n\r\n\t\t\treturn this.panner.refDistance;\r\n\r\n\t\t},\r\n\r\n\t\tsetRefDistance: function ( value ) {\r\n\r\n\t\t\tthis.panner.refDistance = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetRolloffFactor: function () {\r\n\r\n\t\t\treturn this.panner.rolloffFactor;\r\n\r\n\t\t},\r\n\r\n\t\tsetRolloffFactor: function ( value ) {\r\n\r\n\t\t\tthis.panner.rolloffFactor = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetDistanceModel: function () {\r\n\r\n\t\t\treturn this.panner.distanceModel;\r\n\r\n\t\t},\r\n\r\n\t\tsetDistanceModel: function ( value ) {\r\n\r\n\t\t\tthis.panner.distanceModel = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetMaxDistance: function () {\r\n\r\n\t\t\treturn this.panner.maxDistance;\r\n\r\n\t\t},\r\n\r\n\t\tsetMaxDistance: function ( value ) {\r\n\r\n\t\t\tthis.panner.maxDistance = value;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetDirectionalCone: function ( coneInnerAngle, coneOuterAngle, coneOuterGain ) {\r\n\r\n\t\t\tthis.panner.coneInnerAngle = coneInnerAngle;\r\n\t\t\tthis.panner.coneOuterAngle = coneOuterAngle;\r\n\t\t\tthis.panner.coneOuterGain = coneOuterGain;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tupdateMatrixWorld: function ( force ) {\r\n\r\n\t\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t\t\tif ( this.hasPlaybackControl === true && this.isPlaying === false ) { return; }\r\n\r\n\t\t\tthis.matrixWorld.decompose( _position$3, _quaternion$4, _scale$2 );\r\n\r\n\t\t\t_orientation$1.set( 0, 0, 1 ).applyQuaternion( _quaternion$4 );\r\n\r\n\t\t\tvar panner = this.panner;\r\n\r\n\t\t\tif ( panner.positionX ) {\r\n\r\n\t\t\t\t// code path for Chrome and Firefox (see #14393)\r\n\r\n\t\t\t\tvar endTime = this.context.currentTime + this.listener.timeDelta;\r\n\r\n\t\t\t\tpanner.positionX.linearRampToValueAtTime( _position$3.x, endTime );\r\n\t\t\t\tpanner.positionY.linearRampToValueAtTime( _position$3.y, endTime );\r\n\t\t\t\tpanner.positionZ.linearRampToValueAtTime( _position$3.z, endTime );\r\n\t\t\t\tpanner.orientationX.linearRampToValueAtTime( _orientation$1.x, endTime );\r\n\t\t\t\tpanner.orientationY.linearRampToValueAtTime( _orientation$1.y, endTime );\r\n\t\t\t\tpanner.orientationZ.linearRampToValueAtTime( _orientation$1.z, endTime );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tpanner.setPosition( _position$3.x, _position$3.y, _position$3.z );\r\n\t\t\t\tpanner.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AudioAnalyser( audio, fftSize ) {\r\n\r\n\t\tthis.analyser = audio.context.createAnalyser();\r\n\t\tthis.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;\r\n\r\n\t\tthis.data = new Uint8Array( this.analyser.frequencyBinCount );\r\n\r\n\t\taudio.getOutput().connect( this.analyser );\r\n\r\n\t}\r\n\r\n\tObject.assign( AudioAnalyser.prototype, {\r\n\r\n\t\tgetFrequencyData: function () {\r\n\r\n\t\t\tthis.analyser.getByteFrequencyData( this.data );\r\n\r\n\t\t\treturn this.data;\r\n\r\n\t\t},\r\n\r\n\t\tgetAverageFrequency: function () {\r\n\r\n\t\t\tvar value = 0, data = this.getFrequencyData();\r\n\r\n\t\t\tfor ( var i = 0; i < data.length; i ++ ) {\r\n\r\n\t\t\t\tvalue += data[ i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn value / data.length;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Buffered scene graph property that allows weighted accumulation.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction PropertyMixer( binding, typeName, valueSize ) {\r\n\r\n\t\tthis.binding = binding;\r\n\t\tthis.valueSize = valueSize;\r\n\r\n\t\tvar bufferType = Float64Array,\r\n\t\t\tmixFunction;\r\n\r\n\t\tswitch ( typeName ) {\r\n\r\n\t\t\tcase 'quaternion':\r\n\t\t\t\tmixFunction = this._slerp;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'string':\r\n\t\t\tcase 'bool':\r\n\t\t\t\tbufferType = Array;\r\n\t\t\t\tmixFunction = this._select;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tmixFunction = this._lerp;\r\n\r\n\t\t}\r\n\r\n\t\tthis.buffer = new bufferType( valueSize * 4 );\r\n\t\t// layout: [ incoming | accu0 | accu1 | orig ]\r\n\t\t//\r\n\t\t// interpolators can use .buffer as their .result\r\n\t\t// the data then goes to 'incoming'\r\n\t\t//\r\n\t\t// 'accu0' and 'accu1' are used frame-interleaved for\r\n\t\t// the cumulative result and are compared to detect\r\n\t\t// changes\r\n\t\t//\r\n\t\t// 'orig' stores the original state of the property\r\n\r\n\t\tthis._mixBufferRegion = mixFunction;\r\n\r\n\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\tthis.useCount = 0;\r\n\t\tthis.referenceCount = 0;\r\n\r\n\t}\r\n\r\n\tObject.assign( PropertyMixer.prototype, {\r\n\r\n\t\t// accumulate data in the 'incoming' region into 'accu'\r\n\t\taccumulate: function ( accuIndex, weight ) {\r\n\r\n\t\t\t// note: happily accumulating nothing when weight = 0, the caller knows\r\n\t\t\t// the weight and shouldn't have made the call in the first place\r\n\r\n\t\t\tvar buffer = this.buffer,\r\n\t\t\t\tstride = this.valueSize,\r\n\t\t\t\toffset = accuIndex * stride + stride,\r\n\r\n\t\t\t\tcurrentWeight = this.cumulativeWeight;\r\n\r\n\t\t\tif ( currentWeight === 0 ) {\r\n\r\n\t\t\t\t// accuN := incoming * weight\r\n\r\n\t\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ offset + i ] = buffer[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcurrentWeight = weight;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// accuN := accuN + incoming * weight\r\n\r\n\t\t\t\tcurrentWeight += weight;\r\n\t\t\t\tvar mix = weight / currentWeight;\r\n\t\t\t\tthis._mixBufferRegion( buffer, offset, 0, mix, stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cumulativeWeight = currentWeight;\r\n\r\n\t\t},\r\n\r\n\t\t// apply the state of 'accu' to the binding when accus differ\r\n\t\tapply: function ( accuIndex ) {\r\n\r\n\t\t\tvar stride = this.valueSize,\r\n\t\t\t\tbuffer = this.buffer,\r\n\t\t\t\toffset = accuIndex * stride + stride,\r\n\r\n\t\t\t\tweight = this.cumulativeWeight,\r\n\r\n\t\t\t\tbinding = this.binding;\r\n\r\n\t\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\t\tif ( weight < 1 ) {\r\n\r\n\t\t\t\t// accuN := accuN + original * ( 1 - cumulativeWeight )\r\n\r\n\t\t\t\tvar originalValueOffset = stride * 3;\r\n\r\n\t\t\t\tthis._mixBufferRegion(\r\n\t\t\t\t\tbuffer, offset, originalValueOffset, 1 - weight, stride );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = stride, e = stride + stride; i !== e; ++ i ) {\r\n\r\n\t\t\t\tif ( buffer[ i ] !== buffer[ i + stride ] ) {\r\n\r\n\t\t\t\t\t// value has changed -> update scene graph\r\n\r\n\t\t\t\t\tbinding.setValue( buffer, offset );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// remember the state of the bound property and copy it to both accus\r\n\t\tsaveOriginalState: function () {\r\n\r\n\t\t\tvar binding = this.binding;\r\n\r\n\t\t\tvar buffer = this.buffer,\r\n\t\t\t\tstride = this.valueSize,\r\n\r\n\t\t\t\toriginalValueOffset = stride * 3;\r\n\r\n\t\t\tbinding.getValue( buffer, originalValueOffset );\r\n\r\n\t\t\t// accu[0..1] := orig -- initially detect changes against the original\r\n\t\t\tfor ( var i = stride, e = originalValueOffset; i !== e; ++ i ) {\r\n\r\n\t\t\t\tbuffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cumulativeWeight = 0;\r\n\r\n\t\t},\r\n\r\n\t\t// apply the state previously taken via 'saveOriginalState' to the binding\r\n\t\trestoreOriginalState: function () {\r\n\r\n\t\t\tvar originalValueOffset = this.valueSize * 3;\r\n\t\t\tthis.binding.setValue( this.buffer, originalValueOffset );\r\n\r\n\t\t},\r\n\r\n\r\n\t\t// mix functions\r\n\r\n\t\t_select: function ( buffer, dstOffset, srcOffset, t, stride ) {\r\n\r\n\t\t\tif ( t >= 0.5 ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ dstOffset + i ] = buffer[ srcOffset + i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_slerp: function ( buffer, dstOffset, srcOffset, t ) {\r\n\r\n\t\t\tQuaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );\r\n\r\n\t\t},\r\n\r\n\t\t_lerp: function ( buffer, dstOffset, srcOffset, t, stride ) {\r\n\r\n\t\t\tvar s = 1 - t;\r\n\r\n\t\t\tfor ( var i = 0; i !== stride; ++ i ) {\r\n\r\n\t\t\t\tvar j = dstOffset + i;\r\n\r\n\t\t\t\tbuffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A reference to a real property in the scene graph.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\t// Characters [].:/ are reserved for track binding syntax.\r\n\tvar _RESERVED_CHARS_RE = '\\\\[\\\\]\\\\.:\\\\/';\r\n\tvar _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );\r\n\r\n\t// Attempts to allow node names from any language. ES5's `\\w` regexp matches\r\n\t// only latin characters, and the unicode \\p{L} is not yet supported. So\r\n\t// instead, we exclude reserved characters and match everything else.\r\n\tvar _wordChar = '[^' + _RESERVED_CHARS_RE + ']';\r\n\tvar _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\\\.', '' ) + ']';\r\n\r\n\t// Parent directories, delimited by '/' or ':'. Currently unused, but must\r\n\t// be matched to parse the rest of the track name.\r\n\tvar _directoryRe = /((?:WC+[\\/:])*)/.source.replace( 'WC', _wordChar );\r\n\r\n\t// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.\r\n\tvar _nodeRe = /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );\r\n\r\n\t// Object on target node, and accessor. May not contain reserved\r\n\t// characters. Accessor may contain any character except closing bracket.\r\n\tvar _objectRe = /(?:\\.(WC+)(?:\\[(.+)\\])?)?/.source.replace( 'WC', _wordChar );\r\n\r\n\t// Property and accessor. May not contain reserved characters. Accessor may\r\n\t// contain any non-bracket characters.\r\n\tvar _propertyRe = /\\.(WC+)(?:\\[(.+)\\])?/.source.replace( 'WC', _wordChar );\r\n\r\n\tvar _trackRe = new RegExp( ''\r\n\t\t+ '^'\r\n\t\t+ _directoryRe\r\n\t\t+ _nodeRe\r\n\t\t+ _objectRe\r\n\t\t+ _propertyRe\r\n\t\t+ '$'\r\n\t);\r\n\r\n\tvar _supportedObjectNames = [ 'material', 'materials', 'bones' ];\r\n\r\n\tfunction Composite( targetGroup, path, optionalParsedPath ) {\r\n\r\n\t\tvar parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );\r\n\r\n\t\tthis._targetGroup = targetGroup;\r\n\t\tthis._bindings = targetGroup.subscribe_( path, parsedPath );\r\n\r\n\t}\r\n\r\n\tObject.assign( Composite.prototype, {\r\n\r\n\t\tgetValue: function ( array, offset ) {\r\n\r\n\t\t\tthis.bind(); // bind all binding\r\n\r\n\t\t\tvar firstValidIndex = this._targetGroup.nCachedObjects_,\r\n\t\t\t\tbinding = this._bindings[ firstValidIndex ];\r\n\r\n\t\t\t// and only call .getValue on the first\r\n\t\t\tif ( binding !== undefined ) { binding.getValue( array, offset ); }\r\n\r\n\t\t},\r\n\r\n\t\tsetValue: function ( array, offset ) {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].setValue( array, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tbind: function () {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].bind();\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tunbind: function () {\r\n\r\n\t\t\tvar bindings = this._bindings;\r\n\r\n\t\t\tfor ( var i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].unbind();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\r\n\tfunction PropertyBinding( rootNode, path, parsedPath ) {\r\n\r\n\t\tthis.path = path;\r\n\t\tthis.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );\r\n\r\n\t\tthis.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode;\r\n\r\n\t\tthis.rootNode = rootNode;\r\n\r\n\t}\r\n\r\n\tObject.assign( PropertyBinding, {\r\n\r\n\t\tComposite: Composite,\r\n\r\n\t\tcreate: function ( root, path, parsedPath ) {\r\n\r\n\t\t\tif ( ! ( root && root.isAnimationObjectGroup ) ) {\r\n\r\n\t\t\t\treturn new PropertyBinding( root, path, parsedPath );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\treturn new PropertyBinding.Composite( root, path, parsedPath );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Replaces spaces with underscores and removes unsupported characters from\r\n\t\t * node names, to ensure compatibility with parseTrackName().\r\n\t\t *\r\n\t\t * @param {string} name Node name to be sanitized.\r\n\t\t * @return {string}\r\n\t\t */\r\n\t\tsanitizeNodeName: function ( name ) {\r\n\r\n\t\t\treturn name.replace( /\\s/g, '_' ).replace( _reservedRe, '' );\r\n\r\n\t\t},\r\n\r\n\t\tparseTrackName: function ( trackName ) {\r\n\r\n\t\t\tvar matches = _trackRe.exec( trackName );\r\n\r\n\t\t\tif ( ! matches ) {\r\n\r\n\t\t\t\tthrow new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar results = {\r\n\t\t\t\t// directoryName: matches[ 1 ], // (tschw) currently unused\r\n\t\t\t\tnodeName: matches[ 2 ],\r\n\t\t\t\tobjectName: matches[ 3 ],\r\n\t\t\t\tobjectIndex: matches[ 4 ],\r\n\t\t\t\tpropertyName: matches[ 5 ], // required\r\n\t\t\t\tpropertyIndex: matches[ 6 ]\r\n\t\t\t};\r\n\r\n\t\t\tvar lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );\r\n\r\n\t\t\tif ( lastDot !== undefined && lastDot !== - 1 ) {\r\n\r\n\t\t\t\tvar objectName = results.nodeName.substring( lastDot + 1 );\r\n\r\n\t\t\t\t// Object names must be checked against a whitelist. Otherwise, there\r\n\t\t\t\t// is no way to parse 'foo.bar.baz': 'baz' must be a property, but\r\n\t\t\t\t// 'bar' could be the objectName, or part of a nodeName (which can\r\n\t\t\t\t// include '.' characters).\r\n\t\t\t\tif ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {\r\n\r\n\t\t\t\t\tresults.nodeName = results.nodeName.substring( 0, lastDot );\r\n\t\t\t\t\tresults.objectName = objectName;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( results.propertyName === null || results.propertyName.length === 0 ) {\r\n\r\n\t\t\t\tthrow new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn results;\r\n\r\n\t\t},\r\n\r\n\t\tfindNode: function ( root, nodeName ) {\r\n\r\n\t\t\tif ( ! nodeName || nodeName === \"\" || nodeName === \"root\" || nodeName === \".\" || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {\r\n\r\n\t\t\t\treturn root;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// search into skeleton bones.\r\n\t\t\tif ( root.skeleton ) {\r\n\r\n\t\t\t\tvar bone = root.skeleton.getBoneByName( nodeName );\r\n\r\n\t\t\t\tif ( bone !== undefined ) {\r\n\r\n\t\t\t\t\treturn bone;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// search into node subtree.\r\n\t\t\tif ( root.children ) {\r\n\r\n\t\t\t\tvar searchNodeSubtree = function ( children ) {\r\n\r\n\t\t\t\t\tfor ( var i = 0; i < children.length; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar childNode = children[ i ];\r\n\r\n\t\t\t\t\t\tif ( childNode.name === nodeName || childNode.uuid === nodeName ) {\r\n\r\n\t\t\t\t\t\t\treturn childNode;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tvar result = searchNodeSubtree( childNode.children );\r\n\r\n\t\t\t\t\t\tif ( result ) { return result; }\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn null;\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\tvar subTreeNode = searchNodeSubtree( root.children );\r\n\r\n\t\t\t\tif ( subTreeNode ) {\r\n\r\n\t\t\t\t\treturn subTreeNode;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( PropertyBinding.prototype, { // prototype, continued\r\n\r\n\t\t// these are used to \"bind\" a nonexistent property\r\n\t\t_getValue_unavailable: function () {},\r\n\t\t_setValue_unavailable: function () {},\r\n\r\n\t\tBindingType: {\r\n\t\t\tDirect: 0,\r\n\t\t\tEntireArray: 1,\r\n\t\t\tArrayElement: 2,\r\n\t\t\tHasFromToArray: 3\r\n\t\t},\r\n\r\n\t\tVersioning: {\r\n\t\t\tNone: 0,\r\n\t\t\tNeedsUpdate: 1,\r\n\t\t\tMatrixWorldNeedsUpdate: 2\r\n\t\t},\r\n\r\n\t\tGetterByBindingType: [\r\n\r\n\t\t\tfunction getValue_direct( buffer, offset ) {\r\n\r\n\t\t\t\tbuffer[ offset ] = this.node[ this.propertyName ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_array( buffer, offset ) {\r\n\r\n\t\t\t\tvar source = this.resolvedProperty;\r\n\r\n\t\t\t\tfor ( var i = 0, n = source.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tbuffer[ offset ++ ] = source[ i ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_arrayElement( buffer, offset ) {\r\n\r\n\t\t\t\tbuffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tfunction getValue_toArray( buffer, offset ) {\r\n\r\n\t\t\t\tthis.resolvedProperty.toArray( buffer, offset );\r\n\r\n\t\t\t}\r\n\r\n\t\t],\r\n\r\n\t\tSetterByBindingTypeAndVersioning: [\r\n\r\n\t\t\t[\r\n\t\t\t\t// Direct\r\n\r\n\t\t\t\tfunction setValue_direct( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_direct_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.targetObject[ this.propertyName ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// EntireArray\r\n\r\n\t\t\t\tfunction setValue_array( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_array_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tvar dest = this.resolvedProperty;\r\n\r\n\t\t\t\t\tfor ( var i = 0, n = dest.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\t\tdest[ i ] = buffer[ offset ++ ];\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// ArrayElement\r\n\r\n\t\t\t\tfunction setValue_arrayElement( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_arrayElement_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t], [\r\n\r\n\t\t\t\t// HasToFromArray\r\n\r\n\t\t\t\tfunction setValue_fromArray( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_fromArray_setNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\t\t\t\t\tthis.targetObject.needsUpdate = true;\r\n\r\n\t\t\t\t},\r\n\r\n\t\t\t\tfunction setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {\r\n\r\n\t\t\t\t\tthis.resolvedProperty.fromArray( buffer, offset );\r\n\t\t\t\t\tthis.targetObject.matrixWorldNeedsUpdate = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t]\r\n\r\n\t\t],\r\n\r\n\t\tgetValue: function getValue_unbound( targetArray, offset ) {\r\n\r\n\t\t\tthis.bind();\r\n\t\t\tthis.getValue( targetArray, offset );\r\n\r\n\t\t\t// Note: This class uses a State pattern on a per-method basis:\r\n\t\t\t// 'bind' sets 'this.getValue' / 'setValue' and shadows the\r\n\t\t\t// prototype version of these methods with one that represents\r\n\t\t\t// the bound state. When the property is not found, the methods\r\n\t\t\t// become no-ops.\r\n\r\n\t\t},\r\n\r\n\t\tsetValue: function getValue_unbound( sourceArray, offset ) {\r\n\r\n\t\t\tthis.bind();\r\n\t\t\tthis.setValue( sourceArray, offset );\r\n\r\n\t\t},\r\n\r\n\t\t// create getter / setter pair for a property in the scene graph\r\n\t\tbind: function () {\r\n\r\n\t\t\tvar targetObject = this.node,\r\n\t\t\t\tparsedPath = this.parsedPath,\r\n\r\n\t\t\t\tobjectName = parsedPath.objectName,\r\n\t\t\t\tpropertyName = parsedPath.propertyName,\r\n\t\t\t\tpropertyIndex = parsedPath.propertyIndex;\r\n\r\n\t\t\tif ( ! targetObject ) {\r\n\r\n\t\t\t\ttargetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode;\r\n\r\n\t\t\t\tthis.node = targetObject;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// set fail state so we can just 'return' on error\r\n\t\t\tthis.getValue = this._getValue_unavailable;\r\n\t\t\tthis.setValue = this._setValue_unavailable;\r\n\r\n\t\t\t// ensure there is a value node\r\n\t\t\tif ( ! targetObject ) {\r\n\r\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\\'t found.' );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( objectName ) {\r\n\r\n\t\t\t\tvar objectIndex = parsedPath.objectIndex;\r\n\r\n\t\t\t\t// special cases were we need to reach deeper into the hierarchy to get the face materials....\r\n\t\t\t\tswitch ( objectName ) {\r\n\r\n\t\t\t\t\tcase 'materials':\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.material ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.material.materials ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject.material.materials;\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase 'bones':\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.skeleton ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t// potential future optimization: skip this if propertyIndex is already an integer\r\n\t\t\t\t\t\t// and convert the integer string to a true integer.\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject.skeleton.bones;\r\n\r\n\t\t\t\t\t\t// support resolving morphTarget names into indices.\r\n\t\t\t\t\t\tfor ( var i = 0; i < targetObject.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject[ i ].name === objectIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tobjectIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\tif ( targetObject[ objectName ] === undefined ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\ttargetObject = targetObject[ objectName ];\r\n\r\n\t\t\t\t}\r\n\r\n\r\n\t\t\t\tif ( objectIndex !== undefined ) {\r\n\r\n\t\t\t\t\tif ( targetObject[ objectIndex ] === undefined ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttargetObject = targetObject[ objectIndex ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// resolve property\r\n\t\t\tvar nodeProperty = targetObject[ propertyName ];\r\n\r\n\t\t\tif ( nodeProperty === undefined ) {\r\n\r\n\t\t\t\tvar nodeName = parsedPath.nodeName;\r\n\r\n\t\t\t\tconsole.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +\r\n\t\t\t\t\t'.' + propertyName + ' but it wasn\\'t found.', targetObject );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// determine versioning scheme\r\n\t\t\tvar versioning = this.Versioning.None;\r\n\r\n\t\t\tthis.targetObject = targetObject;\r\n\r\n\t\t\tif ( targetObject.needsUpdate !== undefined ) { // material\r\n\r\n\t\t\t\tversioning = this.Versioning.NeedsUpdate;\r\n\r\n\t\t\t} else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform\r\n\r\n\t\t\t\tversioning = this.Versioning.MatrixWorldNeedsUpdate;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// determine how the property gets bound\r\n\t\t\tvar bindingType = this.BindingType.Direct;\r\n\r\n\t\t\tif ( propertyIndex !== undefined ) {\r\n\r\n\t\t\t\t// access a sub element of the property array (only primitives are supported right now)\r\n\r\n\t\t\t\tif ( propertyName === \"morphTargetInfluences\" ) {\r\n\r\n\t\t\t\t\t// potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.\r\n\r\n\t\t\t\t\t// support resolving morphTarget names into indices.\r\n\t\t\t\t\tif ( ! targetObject.geometry ) {\r\n\r\n\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( targetObject.geometry.isBufferGeometry ) {\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphAttributes ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tpropertyIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tif ( ! targetObject.geometry.morphTargets ) {\r\n\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this );\r\n\t\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tfor ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tif ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) {\r\n\r\n\t\t\t\t\t\t\t\tpropertyIndex = i;\r\n\t\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbindingType = this.BindingType.ArrayElement;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\t\t\t\tthis.propertyIndex = propertyIndex;\r\n\r\n\t\t\t} else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {\r\n\r\n\t\t\t\t// must use copy for Object3D.Euler/Quaternion\r\n\r\n\t\t\t\tbindingType = this.BindingType.HasFromToArray;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\r\n\t\t\t} else if ( Array.isArray( nodeProperty ) ) {\r\n\r\n\t\t\t\tbindingType = this.BindingType.EntireArray;\r\n\r\n\t\t\t\tthis.resolvedProperty = nodeProperty;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.propertyName = propertyName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// select getter / setter\r\n\t\t\tthis.getValue = this.GetterByBindingType[ bindingType ];\r\n\t\t\tthis.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];\r\n\r\n\t\t},\r\n\r\n\t\tunbind: function () {\r\n\r\n\t\t\tthis.node = null;\r\n\r\n\t\t\t// back to the prototype version of getValue / setValue\r\n\t\t\t// note: avoiding to mutate the shape of 'this' via 'delete'\r\n\t\t\tthis.getValue = this._getValue_unbound;\r\n\t\t\tthis.setValue = this._setValue_unbound;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//!\\ DECLARE ALIAS AFTER assign prototype !\r\n\tObject.assign( PropertyBinding.prototype, {\r\n\r\n\t\t// initial state of these methods that calls 'bind'\r\n\t\t_getValue_unbound: PropertyBinding.prototype.getValue,\r\n\t\t_setValue_unbound: PropertyBinding.prototype.setValue,\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * A group of objects that receives a shared animation state.\r\n\t *\r\n\t * Usage:\r\n\t *\r\n\t * - Add objects you would otherwise pass as 'root' to the\r\n\t * constructor or the .clipAction method of AnimationMixer.\r\n\t *\r\n\t * - Instead pass this object as 'root'.\r\n\t *\r\n\t * - You can also add and remove objects later when the mixer\r\n\t * is running.\r\n\t *\r\n\t * Note:\r\n\t *\r\n\t * Objects of this class appear as one object to the mixer,\r\n\t * so cache control of the individual objects must be done\r\n\t * on the group.\r\n\t *\r\n\t * Limitation:\r\n\t *\r\n\t * - The animated properties must be compatible among the\r\n\t * all objects in the group.\r\n\t *\r\n\t * - A single property can either be controlled through a\r\n\t * target group or directly, but not both.\r\n\t *\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction AnimationObjectGroup() {\r\n\r\n\t\tthis.uuid = _Math.generateUUID();\r\n\r\n\t\t// cached objects followed by the active ones\r\n\t\tthis._objects = Array.prototype.slice.call( arguments );\r\n\r\n\t\tthis.nCachedObjects_ = 0; // threshold\r\n\t\t// note: read by PropertyBinding.Composite\r\n\r\n\t\tvar indices = {};\r\n\t\tthis._indicesByUUID = indices; // for bookkeeping\r\n\r\n\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\tindices[ arguments[ i ].uuid ] = i;\r\n\r\n\t\t}\r\n\r\n\t\tthis._paths = []; // inside: string\r\n\t\tthis._parsedPaths = []; // inside: { we don't care, here }\r\n\t\tthis._bindings = []; // inside: Array< PropertyBinding >\r\n\t\tthis._bindingsIndicesByPath = {}; // inside: indices in these arrays\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tthis.stats = {\r\n\r\n\t\t\tobjects: {\r\n\t\t\t\tget total() {\r\n\r\n\t\t\t\t\treturn scope._objects.length;\r\n\r\n\t\t\t\t},\r\n\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\treturn this.total - scope.nCachedObjects_;\r\n\r\n\t\t\t\t}\r\n\t\t\t},\r\n\t\t\tget bindingsPerObject() {\r\n\r\n\t\t\t\treturn scope._bindings.length;\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationObjectGroup.prototype, {\r\n\r\n\t\tisAnimationObjectGroup: true,\r\n\r\n\t\tadd: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tpaths = this._paths,\r\n\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length,\r\n\t\t\t\tknownObject = undefined;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index === undefined ) {\r\n\r\n\t\t\t\t\t// unknown object -> add it to the ACTIVE region\r\n\r\n\t\t\t\t\tindex = nObjects ++;\r\n\t\t\t\t\tindicesByUUID[ uuid ] = index;\r\n\t\t\t\t\tobjects.push( object );\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tbindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( index < nCachedObjects ) {\r\n\r\n\t\t\t\t\tknownObject = objects[ index ];\r\n\r\n\t\t\t\t\t// move existing object to the ACTIVE region\r\n\r\n\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\r\n\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ];\r\n\r\n\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\r\n\t\t\t\t\tobjects[ index ] = lastCachedObject;\r\n\r\n\t\t\t\t\tindicesByUUID[ uuid ] = firstActiveIndex;\r\n\t\t\t\t\tobjects[ firstActiveIndex ] = object;\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\r\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\r\n\r\n\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\r\n\r\n\t\t\t\t\t\tif ( binding === undefined ) {\r\n\r\n\t\t\t\t\t\t\t// since we do not bother to create new bindings\r\n\t\t\t\t\t\t\t// for objects that are cached, the binding may\r\n\t\t\t\t\t\t\t// or may not exist\r\n\r\n\t\t\t\t\t\t\tbinding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = binding;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else if ( objects[ index ] !== knownObject ) {\r\n\r\n\t\t\t\t\tconsole.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +\r\n\t\t\t\t\t\t'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );\r\n\r\n\t\t\t\t} // else the object is already where we want it to be\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\tremove: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index !== undefined && index >= nCachedObjects ) {\r\n\r\n\t\t\t\t\t// move existing object into the CACHED region\r\n\r\n\t\t\t\t\tvar lastCachedIndex = nCachedObjects ++,\r\n\t\t\t\t\t\tfirstActiveObject = objects[ lastCachedIndex ];\r\n\r\n\t\t\t\t\tindicesByUUID[ firstActiveObject.uuid ] = index;\r\n\t\t\t\t\tobjects[ index ] = firstActiveObject;\r\n\r\n\t\t\t\t\tindicesByUUID[ uuid ] = lastCachedIndex;\r\n\t\t\t\t\tobjects[ lastCachedIndex ] = object;\r\n\r\n\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\tfirstActive = bindingsForPath[ lastCachedIndex ],\r\n\t\t\t\t\t\t\tbinding = bindingsForPath[ index ];\r\n\r\n\t\t\t\t\t\tbindingsForPath[ index ] = firstActive;\r\n\t\t\t\t\t\tbindingsForPath[ lastCachedIndex ] = binding;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\t// remove & forget\r\n\t\tuncache: function () {\r\n\r\n\t\t\tvar objects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tindicesByUUID = this._indicesByUUID,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = bindings.length;\r\n\r\n\t\t\tfor ( var i = 0, n = arguments.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = arguments[ i ],\r\n\t\t\t\t\tuuid = object.uuid,\r\n\t\t\t\t\tindex = indicesByUUID[ uuid ];\r\n\r\n\t\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\t\tdelete indicesByUUID[ uuid ];\r\n\r\n\t\t\t\t\tif ( index < nCachedObjects ) {\r\n\r\n\t\t\t\t\t\t// object is cached, shrink the CACHED region\r\n\r\n\t\t\t\t\t\tvar firstActiveIndex = -- nCachedObjects,\r\n\t\t\t\t\t\t\tlastCachedObject = objects[ firstActiveIndex ],\r\n\t\t\t\t\t\t\tlastIndex = -- nObjects,\r\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\r\n\r\n\t\t\t\t\t\t// last cached object takes this object's place\r\n\t\t\t\t\t\tindicesByUUID[ lastCachedObject.uuid ] = index;\r\n\t\t\t\t\t\tobjects[ index ] = lastCachedObject;\r\n\r\n\t\t\t\t\t\t// last object goes to the activated slot and pop\r\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = firstActiveIndex;\r\n\t\t\t\t\t\tobjects[ firstActiveIndex ] = lastObject;\r\n\t\t\t\t\t\tobjects.pop();\r\n\r\n\t\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ],\r\n\t\t\t\t\t\t\t\tlastCached = bindingsForPath[ firstActiveIndex ],\r\n\t\t\t\t\t\t\t\tlast = bindingsForPath[ lastIndex ];\r\n\r\n\t\t\t\t\t\t\tbindingsForPath[ index ] = lastCached;\r\n\t\t\t\t\t\t\tbindingsForPath[ firstActiveIndex ] = last;\r\n\t\t\t\t\t\t\tbindingsForPath.pop();\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// object is active, just swap with the last and pop\r\n\r\n\t\t\t\t\t\tvar lastIndex = -- nObjects,\r\n\t\t\t\t\t\t\tlastObject = objects[ lastIndex ];\r\n\r\n\t\t\t\t\t\tindicesByUUID[ lastObject.uuid ] = index;\r\n\t\t\t\t\t\tobjects[ index ] = lastObject;\r\n\t\t\t\t\t\tobjects.pop();\r\n\r\n\t\t\t\t\t\t// accounting is done, now do the same for all bindings\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, m = nBindings; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\t\t\tvar bindingsForPath = bindings[ j ];\r\n\r\n\t\t\t\t\t\t\tbindingsForPath[ index ] = bindingsForPath[ lastIndex ];\r\n\t\t\t\t\t\t\tbindingsForPath.pop();\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} // cached or active\r\n\r\n\t\t\t\t} // if object is known\r\n\r\n\t\t\t} // for arguments\r\n\r\n\t\t\tthis.nCachedObjects_ = nCachedObjects;\r\n\r\n\t\t},\r\n\r\n\t\t// Internal interface used by befriended PropertyBinding.Composite:\r\n\r\n\t\tsubscribe_: function ( path, parsedPath ) {\r\n\r\n\t\t\t// returns an array of bindings for the given path that is changed\r\n\t\t\t// according to the contained objects in the group\r\n\r\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\r\n\t\t\t\tindex = indicesByPath[ path ],\r\n\t\t\t\tbindings = this._bindings;\r\n\r\n\t\t\tif ( index !== undefined ) { return bindings[ index ]; }\r\n\r\n\t\t\tvar paths = this._paths,\r\n\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\tobjects = this._objects,\r\n\t\t\t\tnObjects = objects.length,\r\n\t\t\t\tnCachedObjects = this.nCachedObjects_,\r\n\t\t\t\tbindingsForPath = new Array( nObjects );\r\n\r\n\t\t\tindex = bindings.length;\r\n\r\n\t\t\tindicesByPath[ path ] = index;\r\n\r\n\t\t\tpaths.push( path );\r\n\t\t\tparsedPaths.push( parsedPath );\r\n\t\t\tbindings.push( bindingsForPath );\r\n\r\n\t\t\tfor ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar object = objects[ i ];\r\n\t\t\t\tbindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn bindingsForPath;\r\n\r\n\t\t},\r\n\r\n\t\tunsubscribe_: function ( path ) {\r\n\r\n\t\t\t// tells the group to forget about a property path and no longer\r\n\t\t\t// update the array previously obtained with 'subscribe_'\r\n\r\n\t\t\tvar indicesByPath = this._bindingsIndicesByPath,\r\n\t\t\t\tindex = indicesByPath[ path ];\r\n\r\n\t\t\tif ( index !== undefined ) {\r\n\r\n\t\t\t\tvar paths = this._paths,\r\n\t\t\t\t\tparsedPaths = this._parsedPaths,\r\n\t\t\t\t\tbindings = this._bindings,\r\n\t\t\t\t\tlastBindingsIndex = bindings.length - 1,\r\n\t\t\t\t\tlastBindings = bindings[ lastBindingsIndex ],\r\n\t\t\t\t\tlastBindingsPath = path[ lastBindingsIndex ];\r\n\r\n\t\t\t\tindicesByPath[ lastBindingsPath ] = index;\r\n\r\n\t\t\t\tbindings[ index ] = lastBindings;\r\n\t\t\t\tbindings.pop();\r\n\r\n\t\t\t\tparsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];\r\n\t\t\t\tparsedPaths.pop();\r\n\r\n\t\t\t\tpaths[ index ] = paths[ lastBindingsIndex ];\r\n\t\t\t\tpaths.pop();\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Action provided by AnimationMixer for scheduling clip playback on specific\r\n\t * objects.\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t *\r\n\t */\r\n\r\n\tfunction AnimationAction( mixer, clip, localRoot ) {\r\n\r\n\t\tthis._mixer = mixer;\r\n\t\tthis._clip = clip;\r\n\t\tthis._localRoot = localRoot || null;\r\n\r\n\t\tvar tracks = clip.tracks,\r\n\t\t\tnTracks = tracks.length,\r\n\t\t\tinterpolants = new Array( nTracks );\r\n\r\n\t\tvar interpolantSettings = {\r\n\t\t\tendingStart: ZeroCurvatureEnding,\r\n\t\t\tendingEnd: ZeroCurvatureEnding\r\n\t\t};\r\n\r\n\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\r\n\r\n\t\t\tvar interpolant = tracks[ i ].createInterpolant( null );\r\n\t\t\tinterpolants[ i ] = interpolant;\r\n\t\t\tinterpolant.settings = interpolantSettings;\r\n\r\n\t\t}\r\n\r\n\t\tthis._interpolantSettings = interpolantSettings;\r\n\r\n\t\tthis._interpolants = interpolants; // bound by the mixer\r\n\r\n\t\t// inside: PropertyMixer (managed by the mixer)\r\n\t\tthis._propertyBindings = new Array( nTracks );\r\n\r\n\t\tthis._cacheIndex = null; // for the memory manager\r\n\t\tthis._byClipCacheIndex = null; // for the memory manager\r\n\r\n\t\tthis._timeScaleInterpolant = null;\r\n\t\tthis._weightInterpolant = null;\r\n\r\n\t\tthis.loop = LoopRepeat;\r\n\t\tthis._loopCount = - 1;\r\n\r\n\t\t// global mixer time when the action is to be started\r\n\t\t// it's set back to 'null' upon start of the action\r\n\t\tthis._startTime = null;\r\n\r\n\t\t// scaled local time of the action\r\n\t\t// gets clamped or wrapped to 0..clip.duration according to loop\r\n\t\tthis.time = 0;\r\n\r\n\t\tthis.timeScale = 1;\r\n\t\tthis._effectiveTimeScale = 1;\r\n\r\n\t\tthis.weight = 1;\r\n\t\tthis._effectiveWeight = 1;\r\n\r\n\t\tthis.repetitions = Infinity; // no. of repetitions when looping\r\n\r\n\t\tthis.paused = false; // true -> zero effective time scale\r\n\t\tthis.enabled = true; // false -> zero effective weight\r\n\r\n\t\tthis.clampWhenFinished = false;// keep feeding the last frame?\r\n\r\n\t\tthis.zeroSlopeAtStart = true;// for smooth interpolation w/o separate\r\n\t\tthis.zeroSlopeAtEnd = true;// clips for start, loop and end\r\n\r\n\t}\r\n\r\n\tObject.assign( AnimationAction.prototype, {\r\n\r\n\t\t// State & Scheduling\r\n\r\n\t\tplay: function () {\r\n\r\n\t\t\tthis._mixer._activateAction( this );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstop: function () {\r\n\r\n\t\t\tthis._mixer._deactivateAction( this );\r\n\r\n\t\t\treturn this.reset();\r\n\r\n\t\t},\r\n\r\n\t\treset: function () {\r\n\r\n\t\t\tthis.paused = false;\r\n\t\t\tthis.enabled = true;\r\n\r\n\t\t\tthis.time = 0; // restart clip\r\n\t\t\tthis._loopCount = - 1;// forget previous loops\r\n\t\t\tthis._startTime = null;// forget scheduling\r\n\r\n\t\t\treturn this.stopFading().stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\tisRunning: function () {\r\n\r\n\t\t\treturn this.enabled && ! this.paused && this.timeScale !== 0 &&\r\n\t\t\t\tthis._startTime === null && this._mixer._isActiveAction( this );\r\n\r\n\t\t},\r\n\r\n\t\t// return true when play has been called\r\n\t\tisScheduled: function () {\r\n\r\n\t\t\treturn this._mixer._isActiveAction( this );\r\n\r\n\t\t},\r\n\r\n\t\tstartAt: function ( time ) {\r\n\r\n\t\t\tthis._startTime = time;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetLoop: function ( mode, repetitions ) {\r\n\r\n\t\t\tthis.loop = mode;\r\n\t\t\tthis.repetitions = repetitions;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Weight\r\n\r\n\t\t// set the weight stopping any scheduled fading\r\n\t\t// although .enabled = false yields an effective weight of zero, this\r\n\t\t// method does *not* change .enabled, because it would be confusing\r\n\t\tsetEffectiveWeight: function ( weight ) {\r\n\r\n\t\t\tthis.weight = weight;\r\n\r\n\t\t\t// note: same logic as when updated at runtime\r\n\t\t\tthis._effectiveWeight = this.enabled ? weight : 0;\r\n\r\n\t\t\treturn this.stopFading();\r\n\r\n\t\t},\r\n\r\n\t\t// return the weight considering fading and .enabled\r\n\t\tgetEffectiveWeight: function () {\r\n\r\n\t\t\treturn this._effectiveWeight;\r\n\r\n\t\t},\r\n\r\n\t\tfadeIn: function ( duration ) {\r\n\r\n\t\t\treturn this._scheduleFading( duration, 0, 1 );\r\n\r\n\t\t},\r\n\r\n\t\tfadeOut: function ( duration ) {\r\n\r\n\t\t\treturn this._scheduleFading( duration, 1, 0 );\r\n\r\n\t\t},\r\n\r\n\t\tcrossFadeFrom: function ( fadeOutAction, duration, warp ) {\r\n\r\n\t\t\tfadeOutAction.fadeOut( duration );\r\n\t\t\tthis.fadeIn( duration );\r\n\r\n\t\t\tif ( warp ) {\r\n\r\n\t\t\t\tvar fadeInDuration = this._clip.duration,\r\n\t\t\t\t\tfadeOutDuration = fadeOutAction._clip.duration,\r\n\r\n\t\t\t\t\tstartEndRatio = fadeOutDuration / fadeInDuration,\r\n\t\t\t\t\tendStartRatio = fadeInDuration / fadeOutDuration;\r\n\r\n\t\t\t\tfadeOutAction.warp( 1.0, startEndRatio, duration );\r\n\t\t\t\tthis.warp( endStartRatio, 1.0, duration );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcrossFadeTo: function ( fadeInAction, duration, warp ) {\r\n\r\n\t\t\treturn fadeInAction.crossFadeFrom( this, duration, warp );\r\n\r\n\t\t},\r\n\r\n\t\tstopFading: function () {\r\n\r\n\t\t\tvar weightInterpolant = this._weightInterpolant;\r\n\r\n\t\t\tif ( weightInterpolant !== null ) {\r\n\r\n\t\t\t\tthis._weightInterpolant = null;\r\n\t\t\t\tthis._mixer._takeBackControlInterpolant( weightInterpolant );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Time Scale Control\r\n\r\n\t\t// set the time scale stopping any scheduled warping\r\n\t\t// although .paused = true yields an effective time scale of zero, this\r\n\t\t// method does *not* change .paused, because it would be confusing\r\n\t\tsetEffectiveTimeScale: function ( timeScale ) {\r\n\r\n\t\t\tthis.timeScale = timeScale;\r\n\t\t\tthis._effectiveTimeScale = this.paused ? 0 : timeScale;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\t// return the time scale considering warping and .paused\r\n\t\tgetEffectiveTimeScale: function () {\r\n\r\n\t\t\treturn this._effectiveTimeScale;\r\n\r\n\t\t},\r\n\r\n\t\tsetDuration: function ( duration ) {\r\n\r\n\t\t\tthis.timeScale = this._clip.duration / duration;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\tsyncWith: function ( action ) {\r\n\r\n\t\t\tthis.time = action.time;\r\n\t\t\tthis.timeScale = action.timeScale;\r\n\r\n\t\t\treturn this.stopWarping();\r\n\r\n\t\t},\r\n\r\n\t\thalt: function ( duration ) {\r\n\r\n\t\t\treturn this.warp( this._effectiveTimeScale, 0, duration );\r\n\r\n\t\t},\r\n\r\n\t\twarp: function ( startTimeScale, endTimeScale, duration ) {\r\n\r\n\t\t\tvar mixer = this._mixer, now = mixer.time,\r\n\t\t\t\tinterpolant = this._timeScaleInterpolant,\r\n\r\n\t\t\t\ttimeScale = this.timeScale;\r\n\r\n\t\t\tif ( interpolant === null ) {\r\n\r\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\r\n\t\t\t\tthis._timeScaleInterpolant = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = interpolant.parameterPositions,\r\n\t\t\t\tvalues = interpolant.sampleValues;\r\n\r\n\t\t\ttimes[ 0 ] = now;\r\n\t\t\ttimes[ 1 ] = now + duration;\r\n\r\n\t\t\tvalues[ 0 ] = startTimeScale / timeScale;\r\n\t\t\tvalues[ 1 ] = endTimeScale / timeScale;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tstopWarping: function () {\r\n\r\n\t\t\tvar timeScaleInterpolant = this._timeScaleInterpolant;\r\n\r\n\t\t\tif ( timeScaleInterpolant !== null ) {\r\n\r\n\t\t\t\tthis._timeScaleInterpolant = null;\r\n\t\t\t\tthis._mixer._takeBackControlInterpolant( timeScaleInterpolant );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Object Accessors\r\n\r\n\t\tgetMixer: function () {\r\n\r\n\t\t\treturn this._mixer;\r\n\r\n\t\t},\r\n\r\n\t\tgetClip: function () {\r\n\r\n\t\t\treturn this._clip;\r\n\r\n\t\t},\r\n\r\n\t\tgetRoot: function () {\r\n\r\n\t\t\treturn this._localRoot || this._mixer._root;\r\n\r\n\t\t},\r\n\r\n\t\t// Interna\r\n\r\n\t\t_update: function ( time, deltaTime, timeDirection, accuIndex ) {\r\n\r\n\t\t\t// called by the mixer\r\n\r\n\t\t\tif ( ! this.enabled ) {\r\n\r\n\t\t\t\t// call ._updateWeight() to update ._effectiveWeight\r\n\r\n\t\t\t\tthis._updateWeight( time );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar startTime = this._startTime;\r\n\r\n\t\t\tif ( startTime !== null ) {\r\n\r\n\t\t\t\t// check for scheduled start of action\r\n\r\n\t\t\t\tvar timeRunning = ( time - startTime ) * timeDirection;\r\n\t\t\t\tif ( timeRunning < 0 || timeDirection === 0 ) {\r\n\r\n\t\t\t\t\treturn; // yet to come / don't decide when delta = 0\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// start\r\n\r\n\t\t\t\tthis._startTime = null; // unschedule\r\n\t\t\t\tdeltaTime = timeDirection * timeRunning;\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// apply time scale and advance time\r\n\r\n\t\t\tdeltaTime *= this._updateTimeScale( time );\r\n\t\t\tvar clipTime = this._updateTime( deltaTime );\r\n\r\n\t\t\t// note: _updateTime may disable the action resulting in\r\n\t\t\t// an effective weight of 0\r\n\r\n\t\t\tvar weight = this._updateWeight( time );\r\n\r\n\t\t\tif ( weight > 0 ) {\r\n\r\n\t\t\t\tvar interpolants = this._interpolants;\r\n\t\t\t\tvar propertyMixers = this._propertyBindings;\r\n\r\n\t\t\t\tfor ( var j = 0, m = interpolants.length; j !== m; ++ j ) {\r\n\r\n\t\t\t\t\tinterpolants[ j ].evaluate( clipTime );\r\n\t\t\t\t\tpropertyMixers[ j ].accumulate( accuIndex, weight );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_updateWeight: function ( time ) {\r\n\r\n\t\t\tvar weight = 0;\r\n\r\n\t\t\tif ( this.enabled ) {\r\n\r\n\t\t\t\tweight = this.weight;\r\n\t\t\t\tvar interpolant = this._weightInterpolant;\r\n\r\n\t\t\t\tif ( interpolant !== null ) {\r\n\r\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\r\n\r\n\t\t\t\t\tweight *= interpolantValue;\r\n\r\n\t\t\t\t\tif ( time > interpolant.parameterPositions[ 1 ] ) {\r\n\r\n\t\t\t\t\t\tthis.stopFading();\r\n\r\n\t\t\t\t\t\tif ( interpolantValue === 0 ) {\r\n\r\n\t\t\t\t\t\t\t// faded out, disable\r\n\t\t\t\t\t\t\tthis.enabled = false;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._effectiveWeight = weight;\r\n\t\t\treturn weight;\r\n\r\n\t\t},\r\n\r\n\t\t_updateTimeScale: function ( time ) {\r\n\r\n\t\t\tvar timeScale = 0;\r\n\r\n\t\t\tif ( ! this.paused ) {\r\n\r\n\t\t\t\ttimeScale = this.timeScale;\r\n\r\n\t\t\t\tvar interpolant = this._timeScaleInterpolant;\r\n\r\n\t\t\t\tif ( interpolant !== null ) {\r\n\r\n\t\t\t\t\tvar interpolantValue = interpolant.evaluate( time )[ 0 ];\r\n\r\n\t\t\t\t\ttimeScale *= interpolantValue;\r\n\r\n\t\t\t\t\tif ( time > interpolant.parameterPositions[ 1 ] ) {\r\n\r\n\t\t\t\t\t\tthis.stopWarping();\r\n\r\n\t\t\t\t\t\tif ( timeScale === 0 ) {\r\n\r\n\t\t\t\t\t\t\t// motion has halted, pause\r\n\t\t\t\t\t\t\tthis.paused = true;\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t// warp done - apply final time scale\r\n\t\t\t\t\t\t\tthis.timeScale = timeScale;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._effectiveTimeScale = timeScale;\r\n\t\t\treturn timeScale;\r\n\r\n\t\t},\r\n\r\n\t\t_updateTime: function ( deltaTime ) {\r\n\r\n\t\t\tvar time = this.time + deltaTime;\r\n\t\t\tvar duration = this._clip.duration;\r\n\t\t\tvar loop = this.loop;\r\n\t\t\tvar loopCount = this._loopCount;\r\n\r\n\t\t\tvar pingPong = ( loop === LoopPingPong );\r\n\r\n\t\t\tif ( deltaTime === 0 ) {\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) { return time; }\r\n\r\n\t\t\t\treturn ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( loop === LoopOnce ) {\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) {\r\n\r\n\t\t\t\t\t// just started\r\n\r\n\t\t\t\t\tthis._loopCount = 0;\r\n\t\t\t\t\tthis._setEndings( true, true, false );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\thandle_stop: {\r\n\r\n\t\t\t\t\tif ( time >= duration ) {\r\n\r\n\t\t\t\t\t\ttime = duration;\r\n\r\n\t\t\t\t\t} else if ( time < 0 ) {\r\n\r\n\t\t\t\t\t\ttime = 0;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tbreak handle_stop;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( this.clampWhenFinished ) { this.paused = true; }\r\n\t\t\t\t\telse { this.enabled = false; }\r\n\r\n\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\ttype: 'finished', action: this,\r\n\t\t\t\t\t\tdirection: deltaTime < 0 ? - 1 : 1\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else { // repetitive Repeat or PingPong\r\n\r\n\t\t\t\tif ( loopCount === - 1 ) {\r\n\r\n\t\t\t\t\t// just started\r\n\r\n\t\t\t\t\tif ( deltaTime >= 0 ) {\r\n\r\n\t\t\t\t\t\tloopCount = 0;\r\n\r\n\t\t\t\t\t\tthis._setEndings( true, this.repetitions === 0, pingPong );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// when looping in reverse direction, the initial\r\n\t\t\t\t\t\t// transition through zero counts as a repetition,\r\n\t\t\t\t\t\t// so leave loopCount at -1\r\n\r\n\t\t\t\t\t\tthis._setEndings( this.repetitions === 0, true, pingPong );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( time >= duration || time < 0 ) {\r\n\r\n\t\t\t\t\t// wrap around\r\n\r\n\t\t\t\t\tvar loopDelta = Math.floor( time / duration ); // signed\r\n\t\t\t\t\ttime -= duration * loopDelta;\r\n\r\n\t\t\t\t\tloopCount += Math.abs( loopDelta );\r\n\r\n\t\t\t\t\tvar pending = this.repetitions - loopCount;\r\n\r\n\t\t\t\t\tif ( pending <= 0 ) {\r\n\r\n\t\t\t\t\t\t// have to stop (switch state, clamp time, fire event)\r\n\r\n\t\t\t\t\t\tif ( this.clampWhenFinished ) { this.paused = true; }\r\n\t\t\t\t\t\telse { this.enabled = false; }\r\n\r\n\t\t\t\t\t\ttime = deltaTime > 0 ? duration : 0;\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\t\ttype: 'finished', action: this,\r\n\t\t\t\t\t\t\tdirection: deltaTime > 0 ? 1 : - 1\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t// keep running\r\n\r\n\t\t\t\t\t\tif ( pending === 1 ) {\r\n\r\n\t\t\t\t\t\t\t// entering the last round\r\n\r\n\t\t\t\t\t\t\tvar atStart = deltaTime < 0;\r\n\t\t\t\t\t\t\tthis._setEndings( atStart, ! atStart, pingPong );\r\n\r\n\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\tthis._setEndings( false, false, pingPong );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tthis._loopCount = loopCount;\r\n\r\n\t\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t\t\tthis._mixer.dispatchEvent( {\r\n\t\t\t\t\t\t\ttype: 'loop', action: this, loopDelta: loopDelta\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tthis.time = time;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( pingPong && ( loopCount & 1 ) === 1 ) {\r\n\r\n\t\t\t\t\t// invert time for the \"pong round\"\r\n\r\n\t\t\t\t\treturn duration - time;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn time;\r\n\r\n\t\t},\r\n\r\n\t\t_setEndings: function ( atStart, atEnd, pingPong ) {\r\n\r\n\t\t\tvar settings = this._interpolantSettings;\r\n\r\n\t\t\tif ( pingPong ) {\r\n\r\n\t\t\t\tsettings.endingStart = ZeroSlopeEnding;\r\n\t\t\t\tsettings.endingEnd = ZeroSlopeEnding;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\t// assuming for LoopOnce atStart == atEnd == true\r\n\r\n\t\t\t\tif ( atStart ) {\r\n\r\n\t\t\t\t\tsettings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tsettings.endingStart = WrapAroundEnding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( atEnd ) {\r\n\r\n\t\t\t\t\tsettings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tsettings.endingEnd \t = WrapAroundEnding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_scheduleFading: function ( duration, weightNow, weightThen ) {\r\n\r\n\t\t\tvar mixer = this._mixer, now = mixer.time,\r\n\t\t\t\tinterpolant = this._weightInterpolant;\r\n\r\n\t\t\tif ( interpolant === null ) {\r\n\r\n\t\t\t\tinterpolant = mixer._lendControlInterpolant();\r\n\t\t\t\tthis._weightInterpolant = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar times = interpolant.parameterPositions,\r\n\t\t\t\tvalues = interpolant.sampleValues;\r\n\r\n\t\t\ttimes[ 0 ] = now;\r\n\t\t\tvalues[ 0 ] = weightNow;\r\n\t\t\ttimes[ 1 ] = now + duration;\r\n\t\t\tvalues[ 1 ] = weightThen;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t *\r\n\t * Player for AnimationClips.\r\n\t *\r\n\t *\r\n\t * @author Ben Houston / http://clara.io/\r\n\t * @author David Sarno / http://lighthaus.us/\r\n\t * @author tschw\r\n\t */\r\n\r\n\tfunction AnimationMixer( root ) {\r\n\r\n\t\tthis._root = root;\r\n\t\tthis._initMemoryManager();\r\n\t\tthis._accuIndex = 0;\r\n\r\n\t\tthis.time = 0;\r\n\r\n\t\tthis.timeScale = 1.0;\r\n\r\n\t}\r\n\r\n\tAnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\r\n\r\n\t\tconstructor: AnimationMixer,\r\n\r\n\t\t_bindAction: function ( action, prototypeAction ) {\r\n\r\n\t\t\tvar root = action._localRoot || this._root,\r\n\t\t\t\ttracks = action._clip.tracks,\r\n\t\t\t\tnTracks = tracks.length,\r\n\t\t\t\tbindings = action._propertyBindings,\r\n\t\t\t\tinterpolants = action._interpolants,\r\n\t\t\t\trootUuid = root.uuid,\r\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingsByName = bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( bindingsByName === undefined ) {\r\n\r\n\t\t\t\tbindingsByName = {};\r\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingsByName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i !== nTracks; ++ i ) {\r\n\r\n\t\t\t\tvar track = tracks[ i ],\r\n\t\t\t\t\ttrackName = track.name,\r\n\t\t\t\t\tbinding = bindingsByName[ trackName ];\r\n\r\n\t\t\t\tif ( binding !== undefined ) {\r\n\r\n\t\t\t\t\tbindings[ i ] = binding;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tbinding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( binding !== undefined ) {\r\n\r\n\t\t\t\t\t\t// existing binding, make sure the cache knows\r\n\r\n\t\t\t\t\t\tif ( binding._cacheIndex === null ) {\r\n\r\n\t\t\t\t\t\t\t++ binding.referenceCount;\r\n\t\t\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tcontinue;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar path = prototypeAction && prototypeAction.\r\n\t\t\t\t\t\t_propertyBindings[ i ].binding.parsedPath;\r\n\r\n\t\t\t\t\tbinding = new PropertyMixer(\r\n\t\t\t\t\t\tPropertyBinding.create( root, trackName, path ),\r\n\t\t\t\t\t\ttrack.ValueTypeName, track.getValueSize() );\r\n\r\n\t\t\t\t\t++ binding.referenceCount;\r\n\t\t\t\t\tthis._addInactiveBinding( binding, rootUuid, trackName );\r\n\r\n\t\t\t\t\tbindings[ i ] = binding;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tinterpolants[ i ].resultBuffer = binding.buffer;\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_activateAction: function ( action ) {\r\n\r\n\t\t\tif ( ! this._isActiveAction( action ) ) {\r\n\r\n\t\t\t\tif ( action._cacheIndex === null ) {\r\n\r\n\t\t\t\t\t// this action has been forgotten by the cache, but the user\r\n\t\t\t\t\t// appears to be still using it -> rebind\r\n\r\n\t\t\t\t\tvar rootUuid = ( action._localRoot || this._root ).uuid,\r\n\t\t\t\t\t\tclipUuid = action._clip.uuid,\r\n\t\t\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\r\n\r\n\t\t\t\t\tthis._bindAction( action,\r\n\t\t\t\t\t\tactionsForClip && actionsForClip.knownActions[ 0 ] );\r\n\r\n\t\t\t\t\tthis._addInactiveAction( action, clipUuid, rootUuid );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar bindings = action._propertyBindings;\r\n\r\n\t\t\t\t// increment reference counts / sort out state\r\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( binding.useCount ++ === 0 ) {\r\n\r\n\t\t\t\t\t\tthis._lendBinding( binding );\r\n\t\t\t\t\t\tbinding.saveOriginalState();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._lendAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_deactivateAction: function ( action ) {\r\n\r\n\t\t\tif ( this._isActiveAction( action ) ) {\r\n\r\n\t\t\t\tvar bindings = action._propertyBindings;\r\n\r\n\t\t\t\t// decrement reference counts / sort out state\r\n\t\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\t\tif ( -- binding.useCount === 0 ) {\r\n\r\n\t\t\t\t\t\tbinding.restoreOriginalState();\r\n\t\t\t\t\t\tthis._takeBackBinding( binding );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tthis._takeBackAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// Memory manager\r\n\r\n\t\t_initMemoryManager: function () {\r\n\r\n\t\t\tthis._actions = []; // 'nActiveActions' followed by inactive ones\r\n\t\t\tthis._nActiveActions = 0;\r\n\r\n\t\t\tthis._actionsByClip = {};\r\n\t\t\t// inside:\r\n\t\t\t// {\r\n\t\t\t// \tknownActions: Array< AnimationAction > - used as prototypes\r\n\t\t\t// \tactionByRoot: AnimationAction - lookup\r\n\t\t\t// }\r\n\r\n\r\n\t\t\tthis._bindings = []; // 'nActiveBindings' followed by inactive ones\r\n\t\t\tthis._nActiveBindings = 0;\r\n\r\n\t\t\tthis._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >\r\n\r\n\r\n\t\t\tthis._controlInterpolants = []; // same game as above\r\n\t\t\tthis._nActiveControlInterpolants = 0;\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tthis.stats = {\r\n\r\n\t\t\t\tactions: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._actions.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveActions;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tbindings: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._bindings.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveBindings;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\tcontrolInterpolants: {\r\n\t\t\t\t\tget total() {\r\n\r\n\t\t\t\t\t\treturn scope._controlInterpolants.length;\r\n\r\n\t\t\t\t\t},\r\n\t\t\t\t\tget inUse() {\r\n\r\n\t\t\t\t\t\treturn scope._nActiveControlInterpolants;\r\n\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t};\r\n\r\n\t\t},\r\n\r\n\t\t// Memory management for AnimationAction objects\r\n\r\n\t\t_isActiveAction: function ( action ) {\r\n\r\n\t\t\tvar index = action._cacheIndex;\r\n\t\t\treturn index !== null && index < this._nActiveActions;\r\n\r\n\t\t},\r\n\r\n\t\t_addInactiveAction: function ( action, clipUuid, rootUuid ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip === undefined ) {\r\n\r\n\t\t\t\tactionsForClip = {\r\n\r\n\t\t\t\t\tknownActions: [ action ],\r\n\t\t\t\t\tactionByRoot: {}\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\taction._byClipCacheIndex = 0;\r\n\r\n\t\t\t\tactionsByClip[ clipUuid ] = actionsForClip;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar knownActions = actionsForClip.knownActions;\r\n\r\n\t\t\t\taction._byClipCacheIndex = knownActions.length;\r\n\t\t\t\tknownActions.push( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t\taction._cacheIndex = actions.length;\r\n\t\t\tactions.push( action );\r\n\r\n\t\t\tactionsForClip.actionByRoot[ rootUuid ] = action;\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveAction: function ( action ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ],\r\n\t\t\t\tcacheIndex = action._cacheIndex;\r\n\r\n\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\r\n\t\t\tactions[ cacheIndex ] = lastInactiveAction;\r\n\t\t\tactions.pop();\r\n\r\n\t\t\taction._cacheIndex = null;\r\n\r\n\r\n\t\t\tvar clipUuid = action._clip.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ],\r\n\t\t\t\tknownActionsForClip = actionsForClip.knownActions,\r\n\r\n\t\t\t\tlastKnownAction =\r\n\t\t\t\t\tknownActionsForClip[ knownActionsForClip.length - 1 ],\r\n\r\n\t\t\t\tbyClipCacheIndex = action._byClipCacheIndex;\r\n\r\n\t\t\tlastKnownAction._byClipCacheIndex = byClipCacheIndex;\r\n\t\t\tknownActionsForClip[ byClipCacheIndex ] = lastKnownAction;\r\n\t\t\tknownActionsForClip.pop();\r\n\r\n\t\t\taction._byClipCacheIndex = null;\r\n\r\n\r\n\t\t\tvar actionByRoot = actionsForClip.actionByRoot,\r\n\t\t\t\trootUuid = ( action._localRoot || this._root ).uuid;\r\n\r\n\t\t\tdelete actionByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( knownActionsForClip.length === 0 ) {\r\n\r\n\t\t\t\tdelete actionsByClip[ clipUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis._removeInactiveBindingsForAction( action );\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveBindingsForAction: function ( action ) {\r\n\r\n\t\t\tvar bindings = action._propertyBindings;\r\n\t\t\tfor ( var i = 0, n = bindings.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\tvar binding = bindings[ i ];\r\n\r\n\t\t\t\tif ( -- binding.referenceCount === 0 ) {\r\n\r\n\t\t\t\t\tthis._removeInactiveBinding( binding );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_lendAction: function ( action ) {\r\n\r\n\t\t\t// [ active actions | inactive actions ]\r\n\t\t\t// [ active actions >| inactive actions ]\r\n\t\t\t// s a\r\n\t\t\t// <-swap->\r\n\t\t\t// a s\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tprevIndex = action._cacheIndex,\r\n\r\n\t\t\t\tlastActiveIndex = this._nActiveActions ++,\r\n\r\n\t\t\t\tfirstInactiveAction = actions[ lastActiveIndex ];\r\n\r\n\t\t\taction._cacheIndex = lastActiveIndex;\r\n\t\t\tactions[ lastActiveIndex ] = action;\r\n\r\n\t\t\tfirstInactiveAction._cacheIndex = prevIndex;\r\n\t\t\tactions[ prevIndex ] = firstInactiveAction;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackAction: function ( action ) {\r\n\r\n\t\t\t// [ active actions | inactive actions ]\r\n\t\t\t// [ active actions |< inactive actions ]\r\n\t\t\t// a s\r\n\t\t\t// <-swap->\r\n\t\t\t// s a\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tprevIndex = action._cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveActions,\r\n\r\n\t\t\t\tlastActiveAction = actions[ firstInactiveIndex ];\r\n\r\n\t\t\taction._cacheIndex = firstInactiveIndex;\r\n\t\t\tactions[ firstInactiveIndex ] = action;\r\n\r\n\t\t\tlastActiveAction._cacheIndex = prevIndex;\r\n\t\t\tactions[ prevIndex ] = lastActiveAction;\r\n\r\n\t\t},\r\n\r\n\t\t// Memory management for PropertyMixer objects\r\n\r\n\t\t_addInactiveBinding: function ( binding, rootUuid, trackName ) {\r\n\r\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\r\n\r\n\t\t\t\tbindings = this._bindings;\r\n\r\n\t\t\tif ( bindingByName === undefined ) {\r\n\r\n\t\t\t\tbindingByName = {};\r\n\t\t\t\tbindingsByRoot[ rootUuid ] = bindingByName;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tbindingByName[ trackName ] = binding;\r\n\r\n\t\t\tbinding._cacheIndex = bindings.length;\r\n\t\t\tbindings.push( binding );\r\n\r\n\t\t},\r\n\r\n\t\t_removeInactiveBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tpropBinding = binding.binding,\r\n\t\t\t\trootUuid = propBinding.rootNode.uuid,\r\n\t\t\t\ttrackName = propBinding.path,\r\n\t\t\t\tbindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ],\r\n\r\n\t\t\t\tlastInactiveBinding = bindings[ bindings.length - 1 ],\r\n\t\t\t\tcacheIndex = binding._cacheIndex;\r\n\r\n\t\t\tlastInactiveBinding._cacheIndex = cacheIndex;\r\n\t\t\tbindings[ cacheIndex ] = lastInactiveBinding;\r\n\t\t\tbindings.pop();\r\n\r\n\t\t\tdelete bindingByName[ trackName ];\r\n\r\n\t\t\tif ( Object.keys( bindingByName ).length === 0 ) {\r\n\r\n\t\t\t\tdelete bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t_lendBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tprevIndex = binding._cacheIndex,\r\n\r\n\t\t\t\tlastActiveIndex = this._nActiveBindings ++,\r\n\r\n\t\t\t\tfirstInactiveBinding = bindings[ lastActiveIndex ];\r\n\r\n\t\t\tbinding._cacheIndex = lastActiveIndex;\r\n\t\t\tbindings[ lastActiveIndex ] = binding;\r\n\r\n\t\t\tfirstInactiveBinding._cacheIndex = prevIndex;\r\n\t\t\tbindings[ prevIndex ] = firstInactiveBinding;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackBinding: function ( binding ) {\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tprevIndex = binding._cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveBindings,\r\n\r\n\t\t\t\tlastActiveBinding = bindings[ firstInactiveIndex ];\r\n\r\n\t\t\tbinding._cacheIndex = firstInactiveIndex;\r\n\t\t\tbindings[ firstInactiveIndex ] = binding;\r\n\r\n\t\t\tlastActiveBinding._cacheIndex = prevIndex;\r\n\t\t\tbindings[ prevIndex ] = lastActiveBinding;\r\n\r\n\t\t},\r\n\r\n\r\n\t\t// Memory management of Interpolants for weight and time scale\r\n\r\n\t\t_lendControlInterpolant: function () {\r\n\r\n\t\t\tvar interpolants = this._controlInterpolants,\r\n\t\t\t\tlastActiveIndex = this._nActiveControlInterpolants ++,\r\n\t\t\t\tinterpolant = interpolants[ lastActiveIndex ];\r\n\r\n\t\t\tif ( interpolant === undefined ) {\r\n\r\n\t\t\t\tinterpolant = new LinearInterpolant(\r\n\t\t\t\t\tnew Float32Array( 2 ), new Float32Array( 2 ),\r\n\t\t\t\t\t1, this._controlInterpolantsResultBuffer );\r\n\r\n\t\t\t\tinterpolant.__cacheIndex = lastActiveIndex;\r\n\t\t\t\tinterpolants[ lastActiveIndex ] = interpolant;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn interpolant;\r\n\r\n\t\t},\r\n\r\n\t\t_takeBackControlInterpolant: function ( interpolant ) {\r\n\r\n\t\t\tvar interpolants = this._controlInterpolants,\r\n\t\t\t\tprevIndex = interpolant.__cacheIndex,\r\n\r\n\t\t\t\tfirstInactiveIndex = -- this._nActiveControlInterpolants,\r\n\r\n\t\t\t\tlastActiveInterpolant = interpolants[ firstInactiveIndex ];\r\n\r\n\t\t\tinterpolant.__cacheIndex = firstInactiveIndex;\r\n\t\t\tinterpolants[ firstInactiveIndex ] = interpolant;\r\n\r\n\t\t\tlastActiveInterpolant.__cacheIndex = prevIndex;\r\n\t\t\tinterpolants[ prevIndex ] = lastActiveInterpolant;\r\n\r\n\t\t},\r\n\r\n\t\t_controlInterpolantsResultBuffer: new Float32Array( 1 ),\r\n\r\n\t\t// return an action for a clip optionally using a custom root target\r\n\t\t// object (this method allocates a lot of dynamic memory in case a\r\n\t\t// previously unknown clip/root combination is specified)\r\n\t\tclipAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar root = optionalRoot || this._root,\r\n\t\t\t\trootUuid = root.uuid,\r\n\r\n\t\t\t\tclipObject = typeof clip === 'string' ?\r\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\r\n\r\n\t\t\t\tclipUuid = clipObject !== null ? clipObject.uuid : clip,\r\n\r\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ],\r\n\t\t\t\tprototypeAction = null;\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\tvar existingAction =\r\n\t\t\t\t\t\tactionsForClip.actionByRoot[ rootUuid ];\r\n\r\n\t\t\t\tif ( existingAction !== undefined ) {\r\n\r\n\t\t\t\t\treturn existingAction;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// we know the clip, so we don't have to parse all\r\n\t\t\t\t// the bindings again but can just copy\r\n\t\t\t\tprototypeAction = actionsForClip.knownActions[ 0 ];\r\n\r\n\t\t\t\t// also, take the clip from the prototype action\r\n\t\t\t\tif ( clipObject === null )\r\n\t\t\t\t\t{ clipObject = prototypeAction._clip; }\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// clip must be known when specified via string\r\n\t\t\tif ( clipObject === null ) { return null; }\r\n\r\n\t\t\t// allocate all resources required to run it\r\n\t\t\tvar newAction = new AnimationAction( this, clipObject, optionalRoot );\r\n\r\n\t\t\tthis._bindAction( newAction, prototypeAction );\r\n\r\n\t\t\t// and make the action known to the memory manager\r\n\t\t\tthis._addInactiveAction( newAction, clipUuid, rootUuid );\r\n\r\n\t\t\treturn newAction;\r\n\r\n\t\t},\r\n\r\n\t\t// get an existing action\r\n\t\texistingAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar root = optionalRoot || this._root,\r\n\t\t\t\trootUuid = root.uuid,\r\n\r\n\t\t\t\tclipObject = typeof clip === 'string' ?\r\n\t\t\t\t\tAnimationClip.findByName( root, clip ) : clip,\r\n\r\n\t\t\t\tclipUuid = clipObject ? clipObject.uuid : clip,\r\n\r\n\t\t\t\tactionsForClip = this._actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\treturn actionsForClip.actionByRoot[ rootUuid ] || null;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn null;\r\n\r\n\t\t},\r\n\r\n\t\t// deactivates all previously scheduled actions\r\n\t\tstopAllAction: function () {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tnActions = this._nActiveActions,\r\n\t\t\t\tbindings = this._bindings,\r\n\t\t\t\tnBindings = this._nActiveBindings;\r\n\r\n\t\t\tthis._nActiveActions = 0;\r\n\t\t\tthis._nActiveBindings = 0;\r\n\r\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\r\n\r\n\t\t\t\tactions[ i ].reset();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].useCount = 0;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// advance the time and update apply the animation\r\n\t\tupdate: function ( deltaTime ) {\r\n\r\n\t\t\tdeltaTime *= this.timeScale;\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tnActions = this._nActiveActions,\r\n\r\n\t\t\t\ttime = this.time += deltaTime,\r\n\t\t\t\ttimeDirection = Math.sign( deltaTime ),\r\n\r\n\t\t\t\taccuIndex = this._accuIndex ^= 1;\r\n\r\n\t\t\t// run active actions\r\n\r\n\t\t\tfor ( var i = 0; i !== nActions; ++ i ) {\r\n\r\n\t\t\t\tvar action = actions[ i ];\r\n\r\n\t\t\t\taction._update( time, deltaTime, timeDirection, accuIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// update scene graph\r\n\r\n\t\t\tvar bindings = this._bindings,\r\n\t\t\t\tnBindings = this._nActiveBindings;\r\n\r\n\t\t\tfor ( var i = 0; i !== nBindings; ++ i ) {\r\n\r\n\t\t\t\tbindings[ i ].apply( accuIndex );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// Allows you to seek to a specific time in an animation.\r\n\t\tsetTime: function ( timeInSeconds ) {\r\n\r\n\t\t\tthis.time = 0; // Zero out time attribute for AnimationMixer object;\r\n\t\t\tfor ( var i = 0; i < this._actions.length; i ++ ) {\r\n\r\n\t\t\t\tthis._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.update( timeInSeconds ); // Update used to set exact time. Returns \"this\" AnimationMixer object.\r\n\r\n\t\t},\r\n\r\n\t\t// return this mixer's root target object\r\n\t\tgetRoot: function () {\r\n\r\n\t\t\treturn this._root;\r\n\r\n\t\t},\r\n\r\n\t\t// free all resources specific to a particular clip\r\n\t\tuncacheClip: function ( clip ) {\r\n\r\n\t\t\tvar actions = this._actions,\r\n\t\t\t\tclipUuid = clip.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip,\r\n\t\t\t\tactionsForClip = actionsByClip[ clipUuid ];\r\n\r\n\t\t\tif ( actionsForClip !== undefined ) {\r\n\r\n\t\t\t\t// note: just calling _removeInactiveAction would mess up the\r\n\t\t\t\t// iteration state and also require updating the state we can\r\n\t\t\t\t// just throw away\r\n\r\n\t\t\t\tvar actionsToRemove = actionsForClip.knownActions;\r\n\r\n\t\t\t\tfor ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) {\r\n\r\n\t\t\t\t\tvar action = actionsToRemove[ i ];\r\n\r\n\t\t\t\t\tthis._deactivateAction( action );\r\n\r\n\t\t\t\t\tvar cacheIndex = action._cacheIndex,\r\n\t\t\t\t\t\tlastInactiveAction = actions[ actions.length - 1 ];\r\n\r\n\t\t\t\t\taction._cacheIndex = null;\r\n\t\t\t\t\taction._byClipCacheIndex = null;\r\n\r\n\t\t\t\t\tlastInactiveAction._cacheIndex = cacheIndex;\r\n\t\t\t\t\tactions[ cacheIndex ] = lastInactiveAction;\r\n\t\t\t\t\tactions.pop();\r\n\r\n\t\t\t\t\tthis._removeInactiveBindingsForAction( action );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tdelete actionsByClip[ clipUuid ];\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// free all resources specific to a particular root target object\r\n\t\tuncacheRoot: function ( root ) {\r\n\r\n\t\t\tvar rootUuid = root.uuid,\r\n\t\t\t\tactionsByClip = this._actionsByClip;\r\n\r\n\t\t\tfor ( var clipUuid in actionsByClip ) {\r\n\r\n\t\t\t\tvar actionByRoot = actionsByClip[ clipUuid ].actionByRoot,\r\n\t\t\t\t\taction = actionByRoot[ rootUuid ];\r\n\r\n\t\t\t\tif ( action !== undefined ) {\r\n\r\n\t\t\t\t\tthis._deactivateAction( action );\r\n\t\t\t\t\tthis._removeInactiveAction( action );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar bindingsByRoot = this._bindingsByRootAndName,\r\n\t\t\t\tbindingByName = bindingsByRoot[ rootUuid ];\r\n\r\n\t\t\tif ( bindingByName !== undefined ) {\r\n\r\n\t\t\t\tfor ( var trackName in bindingByName ) {\r\n\r\n\t\t\t\t\tvar binding = bindingByName[ trackName ];\r\n\t\t\t\t\tbinding.restoreOriginalState();\r\n\t\t\t\t\tthis._removeInactiveBinding( binding );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\t// remove a targeted clip from the cache\r\n\t\tuncacheAction: function ( clip, optionalRoot ) {\r\n\r\n\t\t\tvar action = this.existingAction( clip, optionalRoot );\r\n\r\n\t\t\tif ( action !== null ) {\r\n\r\n\t\t\t\tthis._deactivateAction( action );\r\n\t\t\t\tthis._removeInactiveAction( action );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Uniform( value ) {\r\n\r\n\t\tif ( typeof value === 'string' ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Uniform: Type parameter is no longer needed.' );\r\n\t\t\tvalue = arguments[ 1 ];\r\n\r\n\t\t}\r\n\r\n\t\tthis.value = value;\r\n\r\n\t}\r\n\r\n\tUniform.prototype.clone = function () {\r\n\r\n\t\treturn new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );\r\n\r\n\t};\n\n\t/**\r\n\t * @author benaadams / https://twitter.com/ben_a_adams\r\n\t */\r\n\r\n\tfunction InstancedInterleavedBuffer( array, stride, meshPerAttribute ) {\r\n\r\n\t\tInterleavedBuffer.call( this, array, stride );\r\n\r\n\t\tthis.meshPerAttribute = meshPerAttribute || 1;\r\n\r\n\t}\r\n\r\n\tInstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), {\r\n\r\n\t\tconstructor: InstancedInterleavedBuffer,\r\n\r\n\t\tisInstancedInterleavedBuffer: true,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tInterleavedBuffer.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.meshPerAttribute = source.meshPerAttribute;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author bhouston / http://clara.io/\r\n\t * @author stephomi / http://stephaneginier.com/\r\n\t */\r\n\r\n\tfunction Raycaster( origin, direction, near, far ) {\r\n\r\n\t\tthis.ray = new Ray( origin, direction );\r\n\t\t// direction is assumed to be normalized (for accurate distance calculations)\r\n\r\n\t\tthis.near = near || 0;\r\n\t\tthis.far = far || Infinity;\r\n\t\tthis.camera = null;\r\n\r\n\t\tthis.params = {\r\n\t\t\tMesh: {},\r\n\t\t\tLine: {},\r\n\t\t\tLOD: {},\r\n\t\t\tPoints: { threshold: 1 },\r\n\t\t\tSprite: {}\r\n\t\t};\r\n\r\n\t\tObject.defineProperties( this.params, {\r\n\t\t\tPointCloud: {\r\n\t\t\t\tget: function () {\r\n\r\n\t\t\t\t\tconsole.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' );\r\n\t\t\t\t\treturn this.Points;\r\n\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\tfunction ascSort( a, b ) {\r\n\r\n\t\treturn a.distance - b.distance;\r\n\r\n\t}\r\n\r\n\tfunction intersectObject( object, raycaster, intersects, recursive ) {\r\n\r\n\t\tif ( object.visible === false ) { return; }\r\n\r\n\t\tobject.raycast( raycaster, intersects );\r\n\r\n\t\tif ( recursive === true ) {\r\n\r\n\t\t\tvar children = object.children;\r\n\r\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tintersectObject( children[ i ], raycaster, intersects, true );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tObject.assign( Raycaster.prototype, {\r\n\r\n\t\tlinePrecision: 1,\r\n\r\n\t\tset: function ( origin, direction ) {\r\n\r\n\t\t\t// direction is assumed to be normalized (for accurate distance calculations)\r\n\r\n\t\t\tthis.ray.set( origin, direction );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCamera: function ( coords, camera ) {\r\n\r\n\t\t\tif ( ( camera && camera.isPerspectiveCamera ) ) {\r\n\r\n\t\t\t\tthis.ray.origin.setFromMatrixPosition( camera.matrixWorld );\r\n\t\t\t\tthis.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();\r\n\t\t\t\tthis.camera = camera;\r\n\r\n\t\t\t} else if ( ( camera && camera.isOrthographicCamera ) ) {\r\n\r\n\t\t\t\tthis.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera\r\n\t\t\t\tthis.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );\r\n\t\t\t\tthis.camera = camera;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Raycaster: Unsupported camera type.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t},\r\n\r\n\t\tintersectObject: function ( object, recursive, optionalTarget ) {\r\n\r\n\t\t\tvar intersects = optionalTarget || [];\r\n\r\n\t\t\tintersectObject( object, this, intersects, recursive );\r\n\r\n\t\t\tintersects.sort( ascSort );\r\n\r\n\t\t\treturn intersects;\r\n\r\n\t\t},\r\n\r\n\t\tintersectObjects: function ( objects, recursive, optionalTarget ) {\r\n\r\n\t\t\tvar intersects = optionalTarget || [];\r\n\r\n\t\t\tif ( Array.isArray( objects ) === false ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' );\r\n\t\t\t\treturn intersects;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tfor ( var i = 0, l = objects.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tintersectObject( objects[ i ], this, intersects, recursive );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tintersects.sort( ascSort );\r\n\r\n\t\t\treturn intersects;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system\r\n\t *\r\n\t * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.\r\n\t * The azimuthal angle (theta) is measured from the positive z-axis.\r\n\t */\r\n\r\n\tfunction Spherical( radius, phi, theta ) {\r\n\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0;\r\n\t\tthis.phi = ( phi !== undefined ) ? phi : 0; // polar angle\r\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle\r\n\r\n\t\treturn this;\r\n\r\n\t}\r\n\r\n\tObject.assign( Spherical.prototype, {\r\n\r\n\t\tset: function ( radius, phi, theta ) {\r\n\r\n\t\t\tthis.radius = radius;\r\n\t\t\tthis.phi = phi;\r\n\t\t\tthis.theta = theta;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( other ) {\r\n\r\n\t\t\tthis.radius = other.radius;\r\n\t\t\tthis.phi = other.phi;\r\n\t\t\tthis.theta = other.theta;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\t// restrict phi to be betwee EPS and PI-EPS\r\n\t\tmakeSafe: function () {\r\n\r\n\t\t\tvar EPS = 0.000001;\r\n\t\t\tthis.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v ) {\r\n\r\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\r\n\r\n\t\t\tthis.radius = Math.sqrt( x * x + y * y + z * z );\r\n\r\n\t\t\tif ( this.radius === 0 ) {\r\n\r\n\t\t\t\tthis.theta = 0;\r\n\t\t\t\tthis.phi = 0;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.theta = Math.atan2( x, z );\r\n\t\t\t\tthis.phi = Math.acos( _Math.clamp( y / this.radius, - 1, 1 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system\r\n\t *\r\n\t */\r\n\r\n\tfunction Cylindrical( radius, theta, y ) {\r\n\r\n\t\tthis.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane\r\n\t\tthis.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis\r\n\t\tthis.y = ( y !== undefined ) ? y : 0; // height above the x-z plane\r\n\r\n\t\treturn this;\r\n\r\n\t}\r\n\r\n\tObject.assign( Cylindrical.prototype, {\r\n\r\n\t\tset: function ( radius, theta, y ) {\r\n\r\n\t\t\tthis.radius = radius;\r\n\t\t\tthis.theta = theta;\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( other ) {\r\n\r\n\t\t\tthis.radius = other.radius;\r\n\t\t\tthis.theta = other.theta;\r\n\t\t\tthis.y = other.y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromVector3: function ( v ) {\r\n\r\n\t\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCartesianCoords: function ( x, y, z ) {\r\n\r\n\t\t\tthis.radius = Math.sqrt( x * x + z * z );\r\n\t\t\tthis.theta = Math.atan2( x, z );\r\n\t\t\tthis.y = y;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _vector$7 = new Vector2();\r\n\r\n\tfunction Box2( min, max ) {\r\n\r\n\t\tthis.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity );\r\n\t\tthis.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity );\r\n\r\n\t}\r\n\r\n\tObject.assign( Box2.prototype, {\r\n\r\n\t\tset: function ( min, max ) {\r\n\r\n\t\t\tthis.min.copy( min );\r\n\t\t\tthis.max.copy( max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromPoints: function ( points ) {\r\n\r\n\t\t\tthis.makeEmpty();\r\n\r\n\t\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tthis.expandByPoint( points[ i ] );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetFromCenterAndSize: function ( center, size ) {\r\n\r\n\t\t\tvar halfSize = _vector$7.copy( size ).multiplyScalar( 0.5 );\r\n\t\t\tthis.min.copy( center ).sub( halfSize );\r\n\t\t\tthis.max.copy( center ).add( halfSize );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( box ) {\r\n\r\n\t\t\tthis.min.copy( box.min );\r\n\t\t\tthis.max.copy( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tmakeEmpty: function () {\r\n\r\n\t\t\tthis.min.x = this.min.y = + Infinity;\r\n\t\t\tthis.max.x = this.max.y = - Infinity;\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tisEmpty: function () {\r\n\r\n\t\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\r\n\r\n\t\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tgetSize: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getSize() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );\r\n\r\n\t\t},\r\n\r\n\t\texpandByPoint: function ( point ) {\r\n\r\n\t\t\tthis.min.min( point );\r\n\t\t\tthis.max.max( point );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByVector: function ( vector ) {\r\n\r\n\t\t\tthis.min.sub( vector );\r\n\t\t\tthis.max.add( vector );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\texpandByScalar: function ( scalar ) {\r\n\r\n\t\t\tthis.min.addScalar( - scalar );\r\n\t\t\tthis.max.addScalar( scalar );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsPoint: function ( point ) {\r\n\r\n\t\t\treturn point.x < this.min.x || point.x > this.max.x ||\r\n\t\t\t\tpoint.y < this.min.y || point.y > this.max.y ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tcontainsBox: function ( box ) {\r\n\r\n\t\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\r\n\t\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y;\r\n\r\n\t\t},\r\n\r\n\t\tgetParameter: function ( point, target ) {\r\n\r\n\t\t\t// This can potentially have a divide by zero if the box\r\n\t\t\t// has a size dimension of 0.\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .getParameter() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.set(\r\n\t\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\r\n\t\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y )\r\n\t\t\t);\r\n\r\n\t\t},\r\n\r\n\t\tintersectsBox: function ( box ) {\r\n\r\n\t\t\t// using 4 splitting planes to rule out intersections\r\n\r\n\t\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\r\n\t\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ? false : true;\r\n\r\n\t\t},\r\n\r\n\t\tclampPoint: function ( point, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Box2: .clampPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector2();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.copy( point ).clamp( this.min, this.max );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceToPoint: function ( point ) {\r\n\r\n\t\t\tvar clampedPoint = _vector$7.copy( point ).clamp( this.min, this.max );\r\n\t\t\treturn clampedPoint.sub( point ).length();\r\n\r\n\t\t},\r\n\r\n\t\tintersect: function ( box ) {\r\n\r\n\t\t\tthis.min.max( box.min );\r\n\t\t\tthis.max.min( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tunion: function ( box ) {\r\n\r\n\t\t\tthis.min.min( box.min );\r\n\t\t\tthis.max.max( box.max );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\ttranslate: function ( offset ) {\r\n\r\n\t\t\tthis.min.add( offset );\r\n\t\t\tthis.max.add( offset );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( box ) {\r\n\r\n\t\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author bhouston / http://clara.io\r\n\t */\r\n\r\n\tvar _startP = new Vector3();\r\n\tvar _startEnd = new Vector3();\r\n\r\n\tfunction Line3( start, end ) {\r\n\r\n\t\tthis.start = ( start !== undefined ) ? start : new Vector3();\r\n\t\tthis.end = ( end !== undefined ) ? end : new Vector3();\r\n\r\n\t}\r\n\r\n\tObject.assign( Line3.prototype, {\r\n\r\n\t\tset: function ( start, end ) {\r\n\r\n\t\t\tthis.start.copy( start );\r\n\t\t\tthis.end.copy( end );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t},\r\n\r\n\t\tcopy: function ( line ) {\r\n\r\n\t\t\tthis.start.copy( line.start );\r\n\t\t\tthis.end.copy( line.end );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tgetCenter: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .getCenter() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );\r\n\r\n\t\t},\r\n\r\n\t\tdelta: function ( target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .delta() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn target.subVectors( this.end, this.start );\r\n\r\n\t\t},\r\n\r\n\t\tdistanceSq: function () {\r\n\r\n\t\t\treturn this.start.distanceToSquared( this.end );\r\n\r\n\t\t},\r\n\r\n\t\tdistance: function () {\r\n\r\n\t\t\treturn this.start.distanceTo( this.end );\r\n\r\n\t\t},\r\n\r\n\t\tat: function ( t, target ) {\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .at() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPointParameter: function ( point, clampToLine ) {\r\n\r\n\t\t\t_startP.subVectors( point, this.start );\r\n\t\t\t_startEnd.subVectors( this.end, this.start );\r\n\r\n\t\t\tvar startEnd2 = _startEnd.dot( _startEnd );\r\n\t\t\tvar startEnd_startP = _startEnd.dot( _startP );\r\n\r\n\t\t\tvar t = startEnd_startP / startEnd2;\r\n\r\n\t\t\tif ( clampToLine ) {\r\n\r\n\t\t\t\tt = _Math.clamp( t, 0, 1 );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn t;\r\n\r\n\t\t},\r\n\r\n\t\tclosestPointToPoint: function ( point, clampToLine, target ) {\r\n\r\n\t\t\tvar t = this.closestPointToPointParameter( point, clampToLine );\r\n\r\n\t\t\tif ( target === undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Line3: .closestPointToPoint() target is now required' );\r\n\t\t\t\ttarget = new Vector3();\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.delta( target ).multiplyScalar( t ).add( this.start );\r\n\r\n\t\t},\r\n\r\n\t\tapplyMatrix4: function ( matrix ) {\r\n\r\n\t\t\tthis.start.applyMatrix4( matrix );\r\n\t\t\tthis.end.applyMatrix4( matrix );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tequals: function ( line ) {\r\n\r\n\t\t\treturn line.start.equals( this.start ) && line.end.equals( this.end );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t */\r\n\r\n\tfunction ImmediateRenderObject( material ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.material = material;\r\n\t\tthis.render = function ( /* renderCallback */ ) {};\r\n\r\n\t}\r\n\r\n\tImmediateRenderObject.prototype = Object.create( Object3D.prototype );\r\n\tImmediateRenderObject.prototype.constructor = ImmediateRenderObject;\r\n\r\n\tImmediateRenderObject.prototype.isImmediateRenderObject = true;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$5 = new Vector3();\r\n\tvar _v2$3 = new Vector3();\r\n\tvar _normalMatrix$1 = new Matrix3();\r\n\tvar _keys = [ 'a', 'b', 'c' ];\r\n\r\n\tfunction VertexNormalsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xff0000;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar nNormals = 0;\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.faces.length * 3;\r\n\r\n\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.attributes.normal.count;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tVertexNormalsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tVertexNormalsHelper.prototype.constructor = VertexNormalsHelper;\r\n\r\n\tVertexNormalsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\t_normalMatrix$1.getNormalMatrix( this.object.matrixWorld );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tvar vertices = objGeometry.vertices;\r\n\r\n\t\t\tvar faces = objGeometry.faces;\r\n\r\n\t\t\tvar idx = 0;\r\n\r\n\t\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar vertex = vertices[ face[ _keys[ j ] ] ];\r\n\r\n\t\t\t\t\tvar normal = face.vertexNormals[ j ];\r\n\r\n\t\t\t\t\t_v1$5.copy( vertex ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t\t\t_v2$3.copy( normal ).applyMatrix3( _normalMatrix$1 ).normalize().multiplyScalar( this.size ).add( _v1$5 );\r\n\r\n\t\t\t\t\tposition.setXYZ( idx, _v1$5.x, _v1$5.y, _v1$5.z );\r\n\r\n\t\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\t\tposition.setXYZ( idx, _v2$3.x, _v2$3.y, _v2$3.z );\r\n\r\n\t\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t} else if ( objGeometry && objGeometry.isBufferGeometry ) {\r\n\r\n\t\t\tvar objPos = objGeometry.attributes.position;\r\n\r\n\t\t\tvar objNorm = objGeometry.attributes.normal;\r\n\r\n\t\t\tvar idx = 0;\r\n\r\n\t\t\t// for simplicity, ignore index and drawcalls, and render every normal\r\n\r\n\t\t\tfor ( var j = 0, jl = objPos.count; j < jl; j ++ ) {\r\n\r\n\t\t\t\t_v1$5.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t\t_v2$3.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) );\r\n\r\n\t\t\t\t_v2$3.applyMatrix3( _normalMatrix$1 ).normalize().multiplyScalar( this.size ).add( _v1$5 );\r\n\r\n\t\t\t\tposition.setXYZ( idx, _v1$5.x, _v1$5.y, _v1$5.z );\r\n\r\n\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t\tposition.setXYZ( idx, _v2$3.x, _v2$3.y, _v2$3.z );\r\n\r\n\t\t\t\tidx = idx + 1;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$6 = new Vector3();\r\n\tvar _v2$4 = new Vector3();\r\n\r\n\tfunction VertexTangentsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0x00ffff;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( ! ( objGeometry && objGeometry.isBufferGeometry ) ) {\r\n\r\n\t\t\tconsole.error( 'THREE.VertexTangentsHelper: geometry not an instance of THREE.BufferGeometry.', objGeometry );\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tvar nTangents = objGeometry.attributes.tangent.count;\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nTangents * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tVertexTangentsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tVertexTangentsHelper.prototype.constructor = VertexTangentsHelper;\r\n\r\n\tVertexTangentsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tvar objPos = objGeometry.attributes.position;\r\n\r\n\t\tvar objTan = objGeometry.attributes.tangent;\r\n\r\n\t\tvar idx = 0;\r\n\r\n\t\t// for simplicity, ignore index and drawcalls, and render every tangent\r\n\r\n\t\tfor ( var j = 0, jl = objPos.count; j < jl; j ++ ) {\r\n\r\n\t\t\t_v1$6.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld );\r\n\r\n\t\t\t_v2$4.set( objTan.getX( j ), objTan.getY( j ), objTan.getZ( j ) );\r\n\r\n\t\t\t_v2$4.transformDirection( matrixWorld ).multiplyScalar( this.size ).add( _v1$6 );\r\n\r\n\t\t\tposition.setXYZ( idx, _v1$6.x, _v1$6.y, _v1$6.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t\tposition.setXYZ( idx, _v2$4.x, _v2$4.y, _v2$4.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _vector$8 = new Vector3();\r\n\r\n\tfunction SpotLightHelper( light, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = [\r\n\t\t\t0, 0, 0, \t0, 0, 1,\r\n\t\t\t0, 0, 0, \t1, 0, 1,\r\n\t\t\t0, 0, 0,\t- 1, 0, 1,\r\n\t\t\t0, 0, 0, \t0, 1, 1,\r\n\t\t\t0, 0, 0, \t0, - 1, 1\r\n\t\t];\r\n\r\n\t\tfor ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {\r\n\r\n\t\t\tvar p1 = ( i / l ) * Math.PI * 2;\r\n\t\t\tvar p2 = ( j / l ) * Math.PI * 2;\r\n\r\n\t\t\tpositions.push(\r\n\t\t\t\tMath.cos( p1 ), Math.sin( p1 ), 1,\r\n\t\t\t\tMath.cos( p2 ), Math.sin( p2 ), 1\r\n\t\t\t);\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tthis.cone = new LineSegments( geometry, material );\r\n\t\tthis.add( this.cone );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tSpotLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tSpotLightHelper.prototype.constructor = SpotLightHelper;\r\n\r\n\tSpotLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.cone.geometry.dispose();\r\n\t\tthis.cone.material.dispose();\r\n\r\n\t};\r\n\r\n\tSpotLightHelper.prototype.update = function () {\r\n\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tvar coneLength = this.light.distance ? this.light.distance : 1000;\r\n\t\tvar coneWidth = coneLength * Math.tan( this.light.angle );\r\n\r\n\t\tthis.cone.scale.set( coneWidth, coneWidth, coneLength );\r\n\r\n\t\t_vector$8.setFromMatrixPosition( this.light.target.matrixWorld );\r\n\r\n\t\tthis.cone.lookAt( _vector$8 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.cone.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.cone.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t};\n\n\t/**\r\n\t * @author Sean Griffin / http://twitter.com/sgrif\r\n\t * @author Michael Guerrero / http://realitymeltdown.com\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author ikerr / http://verold.com\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _vector$9 = new Vector3();\r\n\tvar _boneMatrix = new Matrix4();\r\n\tvar _matrixWorldInv = new Matrix4();\r\n\r\n\tfunction getBoneList( object ) {\r\n\r\n\t\tvar boneList = [];\r\n\r\n\t\tif ( object && object.isBone ) {\r\n\r\n\t\t\tboneList.push( object );\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i < object.children.length; i ++ ) {\r\n\r\n\t\t\tboneList.push.apply( boneList, getBoneList( object.children[ i ] ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn boneList;\r\n\r\n\t}\r\n\r\n\tfunction SkeletonHelper( object ) {\r\n\r\n\t\tvar bones = getBoneList( object );\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar color1 = new Color( 0, 0, 1 );\r\n\t\tvar color2 = new Color( 0, 1, 0 );\r\n\r\n\t\tfor ( var i = 0; i < bones.length; i ++ ) {\r\n\r\n\t\t\tvar bone = bones[ i ];\r\n\r\n\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\t\tcolors.push( color1.r, color1.g, color1.b );\r\n\t\t\t\tcolors.push( color2.r, color2.g, color2.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t\tthis.root = object;\r\n\t\tthis.bones = bones;\r\n\r\n\t\tthis.matrix = object.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t}\r\n\r\n\tSkeletonHelper.prototype = Object.create( LineSegments.prototype );\r\n\tSkeletonHelper.prototype.constructor = SkeletonHelper;\r\n\r\n\tSkeletonHelper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar bones = this.bones;\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar position = geometry.getAttribute( 'position' );\r\n\r\n\t\t_matrixWorldInv.getInverse( this.root.matrixWorld );\r\n\r\n\t\tfor ( var i = 0, j = 0; i < bones.length; i ++ ) {\r\n\r\n\t\t\tvar bone = bones[ i ];\r\n\r\n\t\t\tif ( bone.parent && bone.parent.isBone ) {\r\n\r\n\t\t\t\t_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );\r\n\t\t\t\t_vector$9.setFromMatrixPosition( _boneMatrix );\r\n\t\t\t\tposition.setXYZ( j, _vector$9.x, _vector$9.y, _vector$9.z );\r\n\r\n\t\t\t\t_boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );\r\n\t\t\t\t_vector$9.setFromMatrixPosition( _boneMatrix );\r\n\t\t\t\tposition.setXYZ( j + 1, _vector$9.x, _vector$9.y, _vector$9.z );\r\n\r\n\t\t\t\tj += 2;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction PointLightHelper( light, sphereSize, color ) {\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new SphereBufferGeometry( sphereSize, 4, 2 );\r\n\t\tvar material = new MeshBasicMaterial( { wireframe: true, fog: false } );\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.matrix = this.light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\r\n\t\t/*\r\n\t\tvar distanceGeometry = new THREE.IcosahedronBufferGeometry( 1, 2 );\r\n\t\tvar distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );\r\n\r\n\t\tthis.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );\r\n\t\tthis.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );\r\n\r\n\t\tvar d = light.distance;\r\n\r\n\t\tif ( d === 0.0 ) {\r\n\r\n\t\t\tthis.lightDistance.visible = false;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightDistance.scale.set( d, d, d );\r\n\r\n\t\t}\r\n\r\n\t\tthis.add( this.lightDistance );\r\n\t\t*/\r\n\r\n\t}\r\n\r\n\tPointLightHelper.prototype = Object.create( Mesh.prototype );\r\n\tPointLightHelper.prototype.constructor = PointLightHelper;\r\n\r\n\tPointLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\r\n\t};\r\n\r\n\tPointLightHelper.prototype.update = function () {\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t\t/*\r\n\t\tvar d = this.light.distance;\r\n\r\n\t\tif ( d === 0.0 ) {\r\n\r\n\t\t\tthis.lightDistance.visible = false;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightDistance.visible = true;\r\n\t\t\tthis.lightDistance.scale.set( d, d, d );\r\n\r\n\t\t}\r\n\t\t*/\r\n\r\n\t};\n\n\t/**\r\n\t * @author abelnation / http://github.com/abelnation\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t *\r\n\t * This helper must be added as a child of the light\r\n\t */\r\n\r\n\tfunction RectAreaLightHelper( light, color ) {\r\n\r\n\t\tthis.type = 'RectAreaLightHelper';\r\n\r\n\t\tthis.light = light;\r\n\r\n\t\tthis.color = color; // optional hardwired color for the helper\r\n\r\n\t\tvar positions = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\t\tgeometry.computeBoundingSphere();\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tLine.call( this, geometry, material );\r\n\r\n\t\t//\r\n\r\n\t\tvar positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];\r\n\r\n\t\tvar geometry2 = new BufferGeometry();\r\n\t\tgeometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\r\n\t\tgeometry2.computeBoundingSphere();\r\n\r\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { side: BackSide, fog: false } ) ) );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tRectAreaLightHelper.prototype = Object.create( Line.prototype );\r\n\tRectAreaLightHelper.prototype.constructor = RectAreaLightHelper;\r\n\r\n\tRectAreaLightHelper.prototype.update = function () {\r\n\r\n\t\tthis.scale.set( 0.5 * this.light.width, 0.5 * this.light.height, 1 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\t\t\tthis.children[ 0 ].material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.material.color.copy( this.light.color ).multiplyScalar( this.light.intensity );\r\n\r\n\t\t\t// prevent hue shift\r\n\t\t\tvar c = this.material.color;\r\n\t\t\tvar max = Math.max( c.r, c.g, c.b );\r\n\t\t\tif ( max > 1 ) { c.multiplyScalar( 1 / max ); }\r\n\r\n\t\t\tthis.children[ 0 ].material.color.copy( this.material.color );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tRectAreaLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\t\tthis.children[ 0 ].geometry.dispose();\r\n\t\tthis.children[ 0 ].material.dispose();\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _vector$a = new Vector3();\r\n\tvar _color1 = new Color();\r\n\tvar _color2 = new Color();\r\n\r\n\tfunction HemisphereLightHelper( light, size, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tvar geometry = new OctahedronBufferGeometry( size );\r\n\t\tgeometry.rotateY( Math.PI * 0.5 );\r\n\r\n\t\tthis.material = new MeshBasicMaterial( { wireframe: true, fog: false } );\r\n\t\tif ( this.color === undefined ) { this.material.vertexColors = VertexColors; }\r\n\r\n\t\tvar position = geometry.getAttribute( 'position' );\r\n\t\tvar colors = new Float32Array( position.count * 3 );\r\n\r\n\t\tgeometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );\r\n\r\n\t\tthis.add( new Mesh( geometry, this.material ) );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tHemisphereLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tHemisphereLightHelper.prototype.constructor = HemisphereLightHelper;\r\n\r\n\tHemisphereLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.children[ 0 ].geometry.dispose();\r\n\t\tthis.children[ 0 ].material.dispose();\r\n\r\n\t};\r\n\r\n\tHemisphereLightHelper.prototype.update = function () {\r\n\r\n\t\tvar mesh = this.children[ 0 ];\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tvar colors = mesh.geometry.getAttribute( 'color' );\r\n\r\n\t\t\t_color1.copy( this.light.color );\r\n\t\t\t_color2.copy( this.light.groundColor );\r\n\r\n\t\t\tfor ( var i = 0, l = colors.count; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar color = ( i < ( l / 2 ) ) ? _color1 : _color2;\r\n\r\n\t\t\t\tcolors.setXYZ( i, color.r, color.g, color.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tcolors.needsUpdate = true;\r\n\r\n\t\t}\r\n\r\n\t\tmesh.lookAt( _vector$a.setFromMatrixPosition( this.light.matrixWorld ).negate() );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction LightProbeHelper( lightProbe, size ) {\r\n\r\n\t\tthis.lightProbe = lightProbe;\r\n\r\n\t\tthis.size = size;\r\n\r\n\t\tvar defines = {};\r\n\t\tdefines[ 'GAMMA_OUTPUT' ] = \"\";\r\n\r\n\t\t// material\r\n\t\tvar material = new ShaderMaterial( {\r\n\r\n\t\t\tdefines: defines,\r\n\r\n\t\t\tuniforms: {\r\n\r\n\t\t\t\tsh: { value: this.lightProbe.sh.coefficients }, // by reference\r\n\r\n\t\t\t\tintensity: { value: this.lightProbe.intensity }\r\n\r\n\t\t\t},\r\n\r\n\t\t\tvertexShader: [\r\n\r\n\t\t\t\t'varying vec3 vNormal;',\r\n\r\n\t\t\t\t'void main() {',\r\n\r\n\t\t\t\t'\tvNormal = normalize( normalMatrix * normal );',\r\n\r\n\t\t\t\t'\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',\r\n\r\n\t\t\t\t'}' ].join( '\\n' ),\r\n\r\n\t\t\tfragmentShader: [\r\n\r\n\t\t\t\t'#define RECIPROCAL_PI 0.318309886',\r\n\r\n\t\t\t\t'vec3 inverseTransformDirection( in vec3 normal, in mat4 matrix ) {',\r\n\r\n\t\t\t\t'\t// matrix is assumed to be orthogonal',\r\n\r\n\t\t\t\t'\treturn normalize( ( vec4( normal, 0.0 ) * matrix ).xyz );',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'vec3 linearToOutput( in vec3 a ) {',\r\n\r\n\t\t\t\t'\t#ifdef GAMMA_OUTPUT',\r\n\r\n\t\t\t\t'\t\treturn pow( a, vec3( 1.0 / float( GAMMA_FACTOR ) ) );',\r\n\r\n\t\t\t\t'\t#else',\r\n\r\n\t\t\t\t'\t\treturn a;',\r\n\r\n\t\t\t\t'\t#endif',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf',\r\n\t\t\t\t'vec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {',\r\n\r\n\t\t\t\t'\t// normal is assumed to have unit length',\r\n\r\n\t\t\t\t'\tfloat x = normal.x, y = normal.y, z = normal.z;',\r\n\r\n\t\t\t\t'\t// band 0',\r\n\t\t\t\t'\tvec3 result = shCoefficients[ 0 ] * 0.886227;',\r\n\r\n\t\t\t\t'\t// band 1',\r\n\t\t\t\t'\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;',\r\n\t\t\t\t'\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;',\r\n\r\n\t\t\t\t'\t// band 2',\r\n\t\t\t\t'\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;',\r\n\t\t\t\t'\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );',\r\n\t\t\t\t'\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;',\r\n\t\t\t\t'\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );',\r\n\r\n\t\t\t\t'\treturn result;',\r\n\r\n\t\t\t\t'}',\r\n\r\n\t\t\t\t'uniform vec3 sh[ 9 ]; // sh coefficients',\r\n\r\n\t\t\t\t'uniform float intensity; // light probe intensity',\r\n\r\n\t\t\t\t'varying vec3 vNormal;',\r\n\r\n\t\t\t\t'void main() {',\r\n\r\n\t\t\t\t'\tvec3 normal = normalize( vNormal );',\r\n\r\n\t\t\t\t'\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );',\r\n\r\n\t\t\t\t'\tvec3 irradiance = shGetIrradianceAt( worldNormal, sh );',\r\n\r\n\t\t\t\t'\tvec3 outgoingLight = RECIPROCAL_PI * irradiance * intensity;',\r\n\r\n\t\t\t\t'\toutgoingLight = linearToOutput( outgoingLight );',\r\n\r\n\t\t\t\t'\tgl_FragColor = vec4( outgoingLight, 1.0 );',\r\n\r\n\t\t\t\t'}'\r\n\r\n\t\t\t].join( '\\n' )\r\n\r\n\t\t} );\r\n\r\n\t\tvar geometry = new SphereBufferGeometry( 1, 32, 16 );\r\n\r\n\t\tMesh.call( this, geometry, material );\r\n\r\n\t\tthis.onBeforeRender();\r\n\r\n\t}\r\n\r\n\tLightProbeHelper.prototype = Object.create( Mesh.prototype );\r\n\tLightProbeHelper.prototype.constructor = LightProbeHelper;\r\n\r\n\tLightProbeHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material.dispose();\r\n\r\n\t};\r\n\r\n\tLightProbeHelper.prototype.onBeforeRender = function () {\r\n\r\n\t\tthis.position.copy( this.lightProbe.position );\r\n\r\n\t\tthis.scale.set( 1, 1, 1 ).multiplyScalar( this.size );\r\n\r\n\t\tthis.material.uniforms.intensity.value = this.lightProbe.intensity;\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction GridHelper( size, divisions, color1, color2 ) {\r\n\r\n\t\tsize = size || 10;\r\n\t\tdivisions = divisions || 10;\r\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\r\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\r\n\r\n\t\tvar center = divisions / 2;\r\n\t\tvar step = size / divisions;\r\n\t\tvar halfSize = size / 2;\r\n\r\n\t\tvar vertices = [], colors = [];\r\n\r\n\t\tfor ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {\r\n\r\n\t\t\tvertices.push( - halfSize, 0, k, halfSize, 0, k );\r\n\t\t\tvertices.push( k, 0, - halfSize, k, 0, halfSize );\r\n\r\n\t\t\tvar color = i === center ? color1 : color2;\r\n\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\t\t\tcolor.toArray( colors, j ); j += 3;\r\n\r\n\t\t}\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tGridHelper.prototype = Object.assign( Object.create( LineSegments.prototype ), {\r\n\r\n\t\tconstructor: GridHelper,\r\n\r\n\t\tcopy: function ( source ) {\r\n\r\n\t\t\tLineSegments.prototype.copy.call( this, source );\r\n\r\n\t\t\tthis.geometry.copy( source.geometry );\r\n\t\t\tthis.material.copy( source.material );\r\n\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tclone: function () {\r\n\r\n\t\t\treturn new this.constructor().copy( this );\r\n\r\n\t\t}\r\n\r\n\t} );\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t * @author Hectate / http://www.github.com/Hectate\r\n\t */\r\n\r\n\tfunction PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) {\r\n\r\n\t\tradius = radius || 10;\r\n\t\tradials = radials || 16;\r\n\t\tcircles = circles || 8;\r\n\t\tdivisions = divisions || 64;\r\n\t\tcolor1 = new Color( color1 !== undefined ? color1 : 0x444444 );\r\n\t\tcolor2 = new Color( color2 !== undefined ? color2 : 0x888888 );\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar x, z;\r\n\t\tvar v, i, j, r, color;\r\n\r\n\t\t// create the radials\r\n\r\n\t\tfor ( i = 0; i <= radials; i ++ ) {\r\n\r\n\t\t\tv = ( i / radials ) * ( Math.PI * 2 );\r\n\r\n\t\t\tx = Math.sin( v ) * radius;\r\n\t\t\tz = Math.cos( v ) * radius;\r\n\r\n\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\tvertices.push( x, 0, z );\r\n\r\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\r\n\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t}\r\n\r\n\t\t// create the circles\r\n\r\n\t\tfor ( i = 0; i <= circles; i ++ ) {\r\n\r\n\t\t\tcolor = ( i & 1 ) ? color1 : color2;\r\n\r\n\t\t\tr = radius - ( radius / circles * i );\r\n\r\n\t\t\tfor ( j = 0; j < divisions; j ++ ) {\r\n\r\n\t\t\t\t// first vertex\r\n\r\n\t\t\t\tv = ( j / divisions ) * ( Math.PI * 2 );\r\n\r\n\t\t\t\tx = Math.sin( v ) * r;\r\n\t\t\t\tz = Math.cos( v ) * r;\r\n\r\n\t\t\t\tvertices.push( x, 0, z );\r\n\t\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\t\t// second vertex\r\n\r\n\t\t\t\tv = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );\r\n\r\n\t\t\t\tx = Math.sin( v ) * r;\r\n\t\t\t\tz = Math.cos( v ) * r;\r\n\r\n\t\t\t\tvertices.push( x, 0, z );\r\n\t\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tPolarGridHelper.prototype = Object.create( LineSegments.prototype );\r\n\tPolarGridHelper.prototype.constructor = PolarGridHelper;\n\n\t/**\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t */\r\n\r\n\tfunction PositionalAudioHelper( audio, range, divisionsInnerAngle, divisionsOuterAngle ) {\r\n\r\n\t\tthis.audio = audio;\r\n\t\tthis.range = range || 1;\r\n\t\tthis.divisionsInnerAngle = divisionsInnerAngle || 16;\r\n\t\tthis.divisionsOuterAngle = divisionsOuterAngle || 2;\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tvar divisions = this.divisionsInnerAngle + this.divisionsOuterAngle * 2;\r\n\t\tvar positions = new Float32Array( ( divisions * 3 + 3 ) * 3 );\r\n\t\tgeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );\r\n\r\n\t\tvar materialInnerAngle = new LineBasicMaterial( { color: 0x00ff00 } );\r\n\t\tvar materialOuterAngle = new LineBasicMaterial( { color: 0xffff00 } );\r\n\r\n\t\tLine.call( this, geometry, [ materialOuterAngle, materialInnerAngle ] );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tPositionalAudioHelper.prototype = Object.create( Line.prototype );\r\n\tPositionalAudioHelper.prototype.constructor = PositionalAudioHelper;\r\n\r\n\tPositionalAudioHelper.prototype.update = function () {\r\n\r\n\t\tvar audio = this.audio;\r\n\t\tvar range = this.range;\r\n\t\tvar divisionsInnerAngle = this.divisionsInnerAngle;\r\n\t\tvar divisionsOuterAngle = this.divisionsOuterAngle;\r\n\r\n\t\tvar coneInnerAngle = _Math.degToRad( audio.panner.coneInnerAngle );\r\n\t\tvar coneOuterAngle = _Math.degToRad( audio.panner.coneOuterAngle );\r\n\r\n\t\tvar halfConeInnerAngle = coneInnerAngle / 2;\r\n\t\tvar halfConeOuterAngle = coneOuterAngle / 2;\r\n\r\n\t\tvar start = 0;\r\n\t\tvar count = 0;\r\n\t\tvar i, stride;\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar positionAttribute = geometry.attributes.position;\r\n\r\n\t\tgeometry.clearGroups();\r\n\r\n\t\t//\r\n\r\n\t\tfunction generateSegment( from, to, divisions, materialIndex ) {\r\n\r\n\t\t\tvar step = ( to - from ) / divisions;\r\n\r\n\t\t\tpositionAttribute.setXYZ( start, 0, 0, 0 );\r\n\t\t\tcount ++;\r\n\r\n\t\t\tfor ( i = from; i < to; i += step ) {\r\n\r\n\t\t\t\tstride = start + count;\r\n\r\n\t\t\t\tpositionAttribute.setXYZ( stride, Math.sin( i ) * range, 0, Math.cos( i ) * range );\r\n\t\t\t\tpositionAttribute.setXYZ( stride + 1, Math.sin( Math.min( i + step, to ) ) * range, 0, Math.cos( Math.min( i + step, to ) ) * range );\r\n\t\t\t\tpositionAttribute.setXYZ( stride + 2, 0, 0, 0 );\r\n\r\n\t\t\t\tcount += 3;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.addGroup( start, count, materialIndex );\r\n\r\n\t\t\tstart += count;\r\n\t\t\tcount = 0;\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tgenerateSegment( - halfConeOuterAngle, - halfConeInnerAngle, divisionsOuterAngle, 0 );\r\n\t\tgenerateSegment( - halfConeInnerAngle, halfConeInnerAngle, divisionsInnerAngle, 1 );\r\n\t\tgenerateSegment( halfConeInnerAngle, halfConeOuterAngle, divisionsOuterAngle, 0 );\r\n\r\n\t\t//\r\n\r\n\t\tpositionAttribute.needsUpdate = true;\r\n\r\n\t\tif ( coneInnerAngle === coneOuterAngle ) { this.material[ 0 ].visible = false; }\r\n\r\n\t};\r\n\r\n\tPositionalAudioHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.geometry.dispose();\r\n\t\tthis.material[ 0 ].dispose();\r\n\t\tthis.material[ 1 ].dispose();\r\n\r\n\t};\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$7 = new Vector3();\r\n\tvar _v2$5 = new Vector3();\r\n\tvar _normalMatrix$2 = new Matrix3();\r\n\r\n\tfunction FaceNormalsHelper( object, size, hex, linewidth ) {\r\n\r\n\t\t// FaceNormalsHelper only supports THREE.Geometry\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tthis.size = ( size !== undefined ) ? size : 1;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\r\n\r\n\t\tvar width = ( linewidth !== undefined ) ? linewidth : 1;\r\n\r\n\t\t//\r\n\r\n\t\tvar nNormals = 0;\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tif ( objGeometry && objGeometry.isGeometry ) {\r\n\r\n\t\t\tnNormals = objGeometry.faces.length;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tconsole.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' );\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tvar positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 );\r\n\r\n\t\tgeometry.setAttribute( 'position', positions );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) );\r\n\r\n\t\t//\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tFaceNormalsHelper.prototype = Object.create( LineSegments.prototype );\r\n\tFaceNormalsHelper.prototype.constructor = FaceNormalsHelper;\r\n\r\n\tFaceNormalsHelper.prototype.update = function () {\r\n\r\n\t\tthis.object.updateMatrixWorld( true );\r\n\r\n\t\t_normalMatrix$2.getNormalMatrix( this.object.matrixWorld );\r\n\r\n\t\tvar matrixWorld = this.object.matrixWorld;\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\r\n\t\t//\r\n\r\n\t\tvar objGeometry = this.object.geometry;\r\n\r\n\t\tvar vertices = objGeometry.vertices;\r\n\r\n\t\tvar faces = objGeometry.faces;\r\n\r\n\t\tvar idx = 0;\r\n\r\n\t\tfor ( var i = 0, l = faces.length; i < l; i ++ ) {\r\n\r\n\t\t\tvar face = faces[ i ];\r\n\r\n\t\t\tvar normal = face.normal;\r\n\r\n\t\t\t_v1$7.copy( vertices[ face.a ] )\r\n\t\t\t\t.add( vertices[ face.b ] )\r\n\t\t\t\t.add( vertices[ face.c ] )\r\n\t\t\t\t.divideScalar( 3 )\r\n\t\t\t\t.applyMatrix4( matrixWorld );\r\n\r\n\t\t\t_v2$5.copy( normal ).applyMatrix3( _normalMatrix$2 ).normalize().multiplyScalar( this.size ).add( _v1$7 );\r\n\r\n\t\t\tposition.setXYZ( idx, _v1$7.x, _v1$7.y, _v1$7.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t\tposition.setXYZ( idx, _v2$5.x, _v2$5.y, _v2$5.z );\r\n\r\n\t\t\tidx = idx + 1;\r\n\r\n\t\t}\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tvar _v1$8 = new Vector3();\r\n\tvar _v2$6 = new Vector3();\r\n\tvar _v3$1 = new Vector3();\r\n\r\n\tfunction DirectionalLightHelper( light, size, color ) {\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tthis.light = light;\r\n\t\tthis.light.updateMatrixWorld();\r\n\r\n\t\tthis.matrix = light.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.color = color;\r\n\r\n\t\tif ( size === undefined ) { size = 1; }\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [\r\n\t\t\t- size, size, 0,\r\n\t\t\tsize, size, 0,\r\n\t\t\tsize, - size, 0,\r\n\t\t\t- size, - size, 0,\r\n\t\t\t- size, size, 0\r\n\t\t], 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { fog: false } );\r\n\r\n\t\tthis.lightPlane = new Line( geometry, material );\r\n\t\tthis.add( this.lightPlane );\r\n\r\n\t\tgeometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );\r\n\r\n\t\tthis.targetLine = new Line( geometry, material );\r\n\t\tthis.add( this.targetLine );\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tDirectionalLightHelper.prototype = Object.create( Object3D.prototype );\r\n\tDirectionalLightHelper.prototype.constructor = DirectionalLightHelper;\r\n\r\n\tDirectionalLightHelper.prototype.dispose = function () {\r\n\r\n\t\tthis.lightPlane.geometry.dispose();\r\n\t\tthis.lightPlane.material.dispose();\r\n\t\tthis.targetLine.geometry.dispose();\r\n\t\tthis.targetLine.material.dispose();\r\n\r\n\t};\r\n\r\n\tDirectionalLightHelper.prototype.update = function () {\r\n\r\n\t\t_v1$8.setFromMatrixPosition( this.light.matrixWorld );\r\n\t\t_v2$6.setFromMatrixPosition( this.light.target.matrixWorld );\r\n\t\t_v3$1.subVectors( _v2$6, _v1$8 );\r\n\r\n\t\tthis.lightPlane.lookAt( _v2$6 );\r\n\r\n\t\tif ( this.color !== undefined ) {\r\n\r\n\t\t\tthis.lightPlane.material.color.set( this.color );\r\n\t\t\tthis.targetLine.material.color.set( this.color );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthis.lightPlane.material.color.copy( this.light.color );\r\n\t\t\tthis.targetLine.material.color.copy( this.light.color );\r\n\r\n\t\t}\r\n\r\n\t\tthis.targetLine.lookAt( _v2$6 );\r\n\t\tthis.targetLine.scale.z = _v3$1.length();\r\n\r\n\t};\n\n\t/**\r\n\t * @author alteredq / http://alteredqualia.com/\r\n\t * @author Mugen87 / https://github.com/Mugen87\r\n\t *\r\n\t *\t- shows frustum, line of sight and up of the camera\r\n\t *\t- suitable for fast updates\r\n\t * \t- based on frustum visualization in lightgl.js shadowmap example\r\n\t *\t\thttp://evanw.github.com/lightgl.js/tests/shadowmap.html\r\n\t */\r\n\r\n\tvar _vector$b = new Vector3();\r\n\tvar _camera = new Camera();\r\n\r\n\tfunction CameraHelper( camera ) {\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tvar material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } );\r\n\r\n\t\tvar vertices = [];\r\n\t\tvar colors = [];\r\n\r\n\t\tvar pointMap = {};\r\n\r\n\t\t// colors\r\n\r\n\t\tvar colorFrustum = new Color( 0xffaa00 );\r\n\t\tvar colorCone = new Color( 0xff0000 );\r\n\t\tvar colorUp = new Color( 0x00aaff );\r\n\t\tvar colorTarget = new Color( 0xffffff );\r\n\t\tvar colorCross = new Color( 0x333333 );\r\n\r\n\t\t// near\r\n\r\n\t\taddLine( 'n1', 'n2', colorFrustum );\r\n\t\taddLine( 'n2', 'n4', colorFrustum );\r\n\t\taddLine( 'n4', 'n3', colorFrustum );\r\n\t\taddLine( 'n3', 'n1', colorFrustum );\r\n\r\n\t\t// far\r\n\r\n\t\taddLine( 'f1', 'f2', colorFrustum );\r\n\t\taddLine( 'f2', 'f4', colorFrustum );\r\n\t\taddLine( 'f4', 'f3', colorFrustum );\r\n\t\taddLine( 'f3', 'f1', colorFrustum );\r\n\r\n\t\t// sides\r\n\r\n\t\taddLine( 'n1', 'f1', colorFrustum );\r\n\t\taddLine( 'n2', 'f2', colorFrustum );\r\n\t\taddLine( 'n3', 'f3', colorFrustum );\r\n\t\taddLine( 'n4', 'f4', colorFrustum );\r\n\r\n\t\t// cone\r\n\r\n\t\taddLine( 'p', 'n1', colorCone );\r\n\t\taddLine( 'p', 'n2', colorCone );\r\n\t\taddLine( 'p', 'n3', colorCone );\r\n\t\taddLine( 'p', 'n4', colorCone );\r\n\r\n\t\t// up\r\n\r\n\t\taddLine( 'u1', 'u2', colorUp );\r\n\t\taddLine( 'u2', 'u3', colorUp );\r\n\t\taddLine( 'u3', 'u1', colorUp );\r\n\r\n\t\t// target\r\n\r\n\t\taddLine( 'c', 't', colorTarget );\r\n\t\taddLine( 'p', 'c', colorCross );\r\n\r\n\t\t// cross\r\n\r\n\t\taddLine( 'cn1', 'cn2', colorCross );\r\n\t\taddLine( 'cn3', 'cn4', colorCross );\r\n\r\n\t\taddLine( 'cf1', 'cf2', colorCross );\r\n\t\taddLine( 'cf3', 'cf4', colorCross );\r\n\r\n\t\tfunction addLine( a, b, color ) {\r\n\r\n\t\t\taddPoint( a, color );\r\n\t\t\taddPoint( b, color );\r\n\r\n\t\t}\r\n\r\n\t\tfunction addPoint( id, color ) {\r\n\r\n\t\t\tvertices.push( 0, 0, 0 );\r\n\t\t\tcolors.push( color.r, color.g, color.b );\r\n\r\n\t\t\tif ( pointMap[ id ] === undefined ) {\r\n\r\n\t\t\t\tpointMap[ id ] = [];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tpointMap[ id ].push( ( vertices.length / 3 ) - 1 );\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t\tthis.camera = camera;\r\n\t\tif ( this.camera.updateProjectionMatrix ) { this.camera.updateProjectionMatrix(); }\r\n\r\n\t\tthis.matrix = camera.matrixWorld;\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.pointMap = pointMap;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tCameraHelper.prototype = Object.create( LineSegments.prototype );\r\n\tCameraHelper.prototype.constructor = CameraHelper;\r\n\r\n\tCameraHelper.prototype.update = function () {\r\n\r\n\t\tvar geometry = this.geometry;\r\n\t\tvar pointMap = this.pointMap;\r\n\r\n\t\tvar w = 1, h = 1;\r\n\r\n\t\t// we need just camera projection matrix inverse\r\n\t\t// world matrix must be identity\r\n\r\n\t\t_camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );\r\n\r\n\t\t// center / target\r\n\r\n\t\tsetPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );\r\n\t\tsetPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );\r\n\r\n\t\t// near\r\n\r\n\t\tsetPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );\r\n\t\tsetPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );\r\n\t\tsetPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );\r\n\t\tsetPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );\r\n\r\n\t\t// far\r\n\r\n\t\tsetPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );\r\n\t\tsetPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );\r\n\t\tsetPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );\r\n\t\tsetPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );\r\n\r\n\t\t// up\r\n\r\n\t\tsetPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );\r\n\t\tsetPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );\r\n\t\tsetPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );\r\n\r\n\t\t// cross\r\n\r\n\t\tsetPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );\r\n\t\tsetPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );\r\n\t\tsetPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );\r\n\t\tsetPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );\r\n\r\n\t\tsetPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );\r\n\t\tsetPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );\r\n\t\tsetPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );\r\n\t\tsetPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );\r\n\r\n\t\tgeometry.getAttribute( 'position' ).needsUpdate = true;\r\n\r\n\t};\r\n\r\n\tfunction setPoint( point, pointMap, geometry, camera, x, y, z ) {\r\n\r\n\t\t_vector$b.set( x, y, z ).unproject( camera );\r\n\r\n\t\tvar points = pointMap[ point ];\r\n\r\n\t\tif ( points !== undefined ) {\r\n\r\n\t\t\tvar position = geometry.getAttribute( 'position' );\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tposition.setXYZ( points[ i ], _vector$b.x, _vector$b.y, _vector$b.z );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t * @author Mugen87 / http://github.com/Mugen87\r\n\t */\r\n\r\n\tvar _box$3 = new Box3();\r\n\r\n\tfunction BoxHelper( object, color ) {\r\n\r\n\t\tthis.object = object;\r\n\r\n\t\tif ( color === undefined ) { color = 0xffff00; }\r\n\r\n\t\tvar 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 ] );\r\n\t\tvar positions = new Float32Array( 8 * 3 );\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\r\n\t\tgeometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\tthis.matrixAutoUpdate = false;\r\n\r\n\t\tthis.update();\r\n\r\n\t}\r\n\r\n\tBoxHelper.prototype = Object.create( LineSegments.prototype );\r\n\tBoxHelper.prototype.constructor = BoxHelper;\r\n\r\n\tBoxHelper.prototype.update = function ( object ) {\r\n\r\n\t\tif ( object !== undefined ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.object !== undefined ) {\r\n\r\n\t\t\t_box$3.setFromObject( this.object );\r\n\r\n\t\t}\r\n\r\n\t\tif ( _box$3.isEmpty() ) { return; }\r\n\r\n\t\tvar min = _box$3.min;\r\n\t\tvar max = _box$3.max;\r\n\r\n\t\t/*\r\n\t\t 5____4\r\n\t\t1/___0/|\r\n\t\t| 6__|_7\r\n\t\t2/___3/\r\n\r\n\t\t0: max.x, max.y, max.z\r\n\t\t1: min.x, max.y, max.z\r\n\t\t2: min.x, min.y, max.z\r\n\t\t3: max.x, min.y, max.z\r\n\t\t4: max.x, max.y, min.z\r\n\t\t5: min.x, max.y, min.z\r\n\t\t6: min.x, min.y, min.z\r\n\t\t7: max.x, min.y, min.z\r\n\t\t*/\r\n\r\n\t\tvar position = this.geometry.attributes.position;\r\n\t\tvar array = position.array;\r\n\r\n\t\tarray[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;\r\n\t\tarray[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;\r\n\t\tarray[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;\r\n\t\tarray[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;\r\n\t\tarray[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;\r\n\t\tarray[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;\r\n\t\tarray[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;\r\n\t\tarray[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;\r\n\r\n\t\tposition.needsUpdate = true;\r\n\r\n\t\tthis.geometry.computeBoundingSphere();\r\n\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.setFromObject = function ( object ) {\r\n\r\n\t\tthis.object = object;\r\n\t\tthis.update();\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.copy = function ( source ) {\r\n\r\n\t\tLineSegments.prototype.copy.call( this, source );\r\n\r\n\t\tthis.object = source.object;\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tBoxHelper.prototype.clone = function () {\r\n\r\n\t\treturn new this.constructor().copy( this );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction Box3Helper( box, color ) {\r\n\r\n\t\tthis.type = 'Box3Helper';\r\n\r\n\t\tthis.box = box;\r\n\r\n\t\tcolor = color || 0xffff00;\r\n\r\n\t\tvar 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 ] );\r\n\r\n\t\tvar 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 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\r\n\t\tgeometry.setIndex( new BufferAttribute( indices, 1 ) );\r\n\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\r\n\t\tLineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\tthis.geometry.computeBoundingSphere();\r\n\r\n\t}\r\n\r\n\tBox3Helper.prototype = Object.create( LineSegments.prototype );\r\n\tBox3Helper.prototype.constructor = Box3Helper;\r\n\r\n\tBox3Helper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar box = this.box;\r\n\r\n\t\tif ( box.isEmpty() ) { return; }\r\n\r\n\t\tbox.getCenter( this.position );\r\n\r\n\t\tbox.getSize( this.scale );\r\n\r\n\t\tthis.scale.multiplyScalar( 0.5 );\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t */\r\n\r\n\tfunction PlaneHelper( plane, size, hex ) {\r\n\r\n\t\tthis.type = 'PlaneHelper';\r\n\r\n\t\tthis.plane = plane;\r\n\r\n\t\tthis.size = ( size === undefined ) ? 1 : size;\r\n\r\n\t\tvar color = ( hex !== undefined ) ? hex : 0xffff00;\r\n\r\n\t\tvar 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 ];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );\r\n\t\tgeometry.computeBoundingSphere();\r\n\r\n\t\tLine.call( this, geometry, new LineBasicMaterial( { color: color } ) );\r\n\r\n\t\t//\r\n\r\n\t\tvar positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ];\r\n\r\n\t\tvar geometry2 = new BufferGeometry();\r\n\t\tgeometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );\r\n\t\tgeometry2.computeBoundingSphere();\r\n\r\n\t\tthis.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) );\r\n\r\n\t}\r\n\r\n\tPlaneHelper.prototype = Object.create( Line.prototype );\r\n\tPlaneHelper.prototype.constructor = PlaneHelper;\r\n\r\n\tPlaneHelper.prototype.updateMatrixWorld = function ( force ) {\r\n\r\n\t\tvar scale = - this.plane.constant;\r\n\r\n\t\tif ( Math.abs( scale ) < 1e-8 ) { scale = 1e-8; } // sign does not matter\r\n\r\n\t\tthis.scale.set( 0.5 * this.size, 0.5 * this.size, scale );\r\n\r\n\t\tthis.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here\r\n\r\n\t\tthis.lookAt( this.plane.normal );\r\n\r\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\r\n\r\n\t};\n\n\t/**\r\n\t * @author WestLangley / http://github.com/WestLangley\r\n\t * @author zz85 / http://github.com/zz85\r\n\t * @author bhouston / http://clara.io\r\n\t *\r\n\t * Creates an arrow for visualizing directions\r\n\t *\r\n\t * Parameters:\r\n\t * dir - Vector3\r\n\t * origin - Vector3\r\n\t * length - Number\r\n\t * color - color in hex value\r\n\t * headLength - Number\r\n\t * headWidth - Number\r\n\t */\r\n\r\n\tvar _axis = new Vector3();\r\n\tvar _lineGeometry, _coneGeometry;\r\n\r\n\tfunction ArrowHelper( dir, origin, length, color, headLength, headWidth ) {\r\n\r\n\t\t// dir is assumed to be normalized\r\n\r\n\t\tObject3D.call( this );\r\n\r\n\t\tif ( dir === undefined ) { dir = new Vector3( 0, 0, 1 ); }\r\n\t\tif ( origin === undefined ) { origin = new Vector3( 0, 0, 0 ); }\r\n\t\tif ( length === undefined ) { length = 1; }\r\n\t\tif ( color === undefined ) { color = 0xffff00; }\r\n\t\tif ( headLength === undefined ) { headLength = 0.2 * length; }\r\n\t\tif ( headWidth === undefined ) { headWidth = 0.2 * headLength; }\r\n\r\n\t\tif ( _lineGeometry === undefined ) {\r\n\r\n\t\t\t_lineGeometry = new BufferGeometry();\r\n\t\t\t_lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );\r\n\r\n\t\t\t_coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 );\r\n\t\t\t_coneGeometry.translate( 0, - 0.5, 0 );\r\n\r\n\t\t}\r\n\r\n\t\tthis.position.copy( origin );\r\n\r\n\t\tthis.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color } ) );\r\n\t\tthis.line.matrixAutoUpdate = false;\r\n\t\tthis.add( this.line );\r\n\r\n\t\tthis.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color } ) );\r\n\t\tthis.cone.matrixAutoUpdate = false;\r\n\t\tthis.add( this.cone );\r\n\r\n\t\tthis.setDirection( dir );\r\n\t\tthis.setLength( length, headLength, headWidth );\r\n\r\n\t}\r\n\r\n\tArrowHelper.prototype = Object.create( Object3D.prototype );\r\n\tArrowHelper.prototype.constructor = ArrowHelper;\r\n\r\n\tArrowHelper.prototype.setDirection = function ( dir ) {\r\n\r\n\t\t// dir is assumed to be normalized\r\n\r\n\t\tif ( dir.y > 0.99999 ) {\r\n\r\n\t\t\tthis.quaternion.set( 0, 0, 0, 1 );\r\n\r\n\t\t} else if ( dir.y < - 0.99999 ) {\r\n\r\n\t\t\tthis.quaternion.set( 1, 0, 0, 0 );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t_axis.set( dir.z, 0, - dir.x ).normalize();\r\n\r\n\t\t\tvar radians = Math.acos( dir.y );\r\n\r\n\t\t\tthis.quaternion.setFromAxisAngle( _axis, radians );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {\r\n\r\n\t\tif ( headLength === undefined ) { headLength = 0.2 * length; }\r\n\t\tif ( headWidth === undefined ) { headWidth = 0.2 * headLength; }\r\n\r\n\t\tthis.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458\r\n\t\tthis.line.updateMatrix();\r\n\r\n\t\tthis.cone.scale.set( headWidth, headLength, headWidth );\r\n\t\tthis.cone.position.y = length;\r\n\t\tthis.cone.updateMatrix();\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.setColor = function ( color ) {\r\n\r\n\t\tthis.line.material.color.set( color );\r\n\t\tthis.cone.material.color.set( color );\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.copy = function ( source ) {\r\n\r\n\t\tObject3D.prototype.copy.call( this, source, false );\r\n\r\n\t\tthis.line.copy( source.line );\r\n\t\tthis.cone.copy( source.cone );\r\n\r\n\t\treturn this;\r\n\r\n\t};\r\n\r\n\tArrowHelper.prototype.clone = function () {\r\n\r\n\t\treturn new this.constructor().copy( this );\r\n\r\n\t};\n\n\t/**\r\n\t * @author sroucheray / http://sroucheray.org/\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction AxesHelper( size ) {\r\n\r\n\t\tsize = size || 1;\r\n\r\n\t\tvar vertices = [\r\n\t\t\t0, 0, 0,\tsize, 0, 0,\r\n\t\t\t0, 0, 0,\t0, size, 0,\r\n\t\t\t0, 0, 0,\t0, 0, size\r\n\t\t];\r\n\r\n\t\tvar colors = [\r\n\t\t\t1, 0, 0,\t1, 0.6, 0,\r\n\t\t\t0, 1, 0,\t0.6, 1, 0,\r\n\t\t\t0, 0, 1,\t0, 0.6, 1\r\n\t\t];\r\n\r\n\t\tvar geometry = new BufferGeometry();\r\n\t\tgeometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\r\n\t\tgeometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );\r\n\r\n\t\tvar material = new LineBasicMaterial( { vertexColors: VertexColors } );\r\n\r\n\t\tLineSegments.call( this, geometry, material );\r\n\r\n\t}\r\n\r\n\tAxesHelper.prototype = Object.create( LineSegments.prototype );\r\n\tAxesHelper.prototype.constructor = AxesHelper;\n\n\t/**\r\n\t * @author mrdoob / http://mrdoob.com/\r\n\t */\r\n\r\n\tfunction Face4( a, b, c, d, normal, color, materialIndex ) {\r\n\r\n\t\tconsole.warn( 'THREE.Face4 has been removed. A THREE.Face3 will be created instead.' );\r\n\t\treturn new Face3( a, b, c, normal, color, materialIndex );\r\n\r\n\t}\r\n\r\n\tvar LineStrip = 0;\r\n\r\n\tvar LinePieces = 1;\r\n\r\n\tfunction MeshFaceMaterial( materials ) {\r\n\r\n\t\tconsole.warn( 'THREE.MeshFaceMaterial has been removed. Use an Array instead.' );\r\n\t\treturn materials;\r\n\r\n\t}\r\n\r\n\tfunction MultiMaterial( materials ) {\r\n\r\n\t\tif ( materials === undefined ) { materials = []; }\r\n\r\n\t\tconsole.warn( 'THREE.MultiMaterial has been removed. Use an Array instead.' );\r\n\t\tmaterials.isMultiMaterial = true;\r\n\t\tmaterials.materials = materials;\r\n\t\tmaterials.clone = function () {\r\n\r\n\t\t\treturn materials.slice();\r\n\r\n\t\t};\r\n\t\treturn materials;\r\n\r\n\t}\r\n\r\n\tfunction PointCloud( geometry, material ) {\r\n\r\n\t\tconsole.warn( 'THREE.PointCloud has been renamed to THREE.Points.' );\r\n\t\treturn new Points( geometry, material );\r\n\r\n\t}\r\n\r\n\tfunction Particle( material ) {\r\n\r\n\t\tconsole.warn( 'THREE.Particle has been renamed to THREE.Sprite.' );\r\n\t\treturn new Sprite( material );\r\n\r\n\t}\r\n\r\n\tfunction ParticleSystem( geometry, material ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleSystem has been renamed to THREE.Points.' );\r\n\t\treturn new Points( geometry, material );\r\n\r\n\t}\r\n\r\n\tfunction PointCloudMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction ParticleBasicMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction ParticleSystemMaterial( parameters ) {\r\n\r\n\t\tconsole.warn( 'THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.' );\r\n\t\treturn new PointsMaterial( parameters );\r\n\r\n\t}\r\n\r\n\tfunction Vertex( x, y, z ) {\r\n\r\n\t\tconsole.warn( 'THREE.Vertex has been removed. Use THREE.Vector3 instead.' );\r\n\t\treturn new Vector3( x, y, z );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction DynamicBufferAttribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.' );\r\n\t\treturn new BufferAttribute( array, itemSize ).setDynamic( true );\r\n\r\n\t}\r\n\r\n\tfunction Int8Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int8Attribute has been removed. Use new THREE.Int8BufferAttribute() instead.' );\r\n\t\treturn new Int8BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint8Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint8Attribute has been removed. Use new THREE.Uint8BufferAttribute() instead.' );\r\n\t\treturn new Uint8BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint8ClampedAttribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint8ClampedAttribute has been removed. Use new THREE.Uint8ClampedBufferAttribute() instead.' );\r\n\t\treturn new Uint8ClampedBufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Int16Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int16Attribute has been removed. Use new THREE.Int16BufferAttribute() instead.' );\r\n\t\treturn new Int16BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint16Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint16Attribute has been removed. Use new THREE.Uint16BufferAttribute() instead.' );\r\n\t\treturn new Uint16BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Int32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Int32Attribute has been removed. Use new THREE.Int32BufferAttribute() instead.' );\r\n\t\treturn new Int32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Uint32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Uint32Attribute has been removed. Use new THREE.Uint32BufferAttribute() instead.' );\r\n\t\treturn new Uint32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Float32Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Float32Attribute has been removed. Use new THREE.Float32BufferAttribute() instead.' );\r\n\t\treturn new Float32BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\tfunction Float64Attribute( array, itemSize ) {\r\n\r\n\t\tconsole.warn( 'THREE.Float64Attribute has been removed. Use new THREE.Float64BufferAttribute() instead.' );\r\n\t\treturn new Float64BufferAttribute( array, itemSize );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tCurve.create = function ( construct, getPoint ) {\r\n\r\n\t\tconsole.log( 'THREE.Curve.create() has been deprecated' );\r\n\r\n\t\tconstruct.prototype = Object.create( Curve.prototype );\r\n\t\tconstruct.prototype.constructor = construct;\r\n\t\tconstruct.prototype.getPoint = getPoint;\r\n\r\n\t\treturn construct;\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tObject.assign( CurvePath.prototype, {\r\n\r\n\t\tcreatePointsGeometry: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\t// generate geometry from path points (for Line or Points objects)\r\n\r\n\t\t\tvar pts = this.getPoints( divisions );\r\n\t\t\treturn this.createGeometry( pts );\r\n\r\n\t\t},\r\n\r\n\t\tcreateSpacedPointsGeometry: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\t// generate geometry from equidistant sampling along the path\r\n\r\n\t\t\tvar pts = this.getSpacedPoints( divisions );\r\n\t\t\treturn this.createGeometry( pts );\r\n\r\n\t\t},\r\n\r\n\t\tcreateGeometry: function ( points ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' );\r\n\r\n\t\t\tvar geometry = new Geometry();\r\n\r\n\t\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar point = points[ i ];\r\n\t\t\t\tgeometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn geometry;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Path.prototype, {\r\n\r\n\t\tfromPoints: function ( points ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' );\r\n\t\t\treturn this.setFromPoints( points );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction ClosedSplineCurve3( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.ClosedSplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\t\tthis.closed = true;\r\n\r\n\t}\r\n\r\n\tClosedSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\t//\r\n\r\n\tfunction SplineCurve3( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.SplineCurve3 has been deprecated. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\r\n\t}\r\n\r\n\tSplineCurve3.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\t//\r\n\r\n\tfunction Spline( points ) {\r\n\r\n\t\tconsole.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' );\r\n\r\n\t\tCatmullRomCurve3.call( this, points );\r\n\t\tthis.type = 'catmullrom';\r\n\r\n\t}\r\n\r\n\tSpline.prototype = Object.create( CatmullRomCurve3.prototype );\r\n\r\n\tObject.assign( Spline.prototype, {\r\n\r\n\t\tinitFromArray: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .initFromArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tgetControlPointsArray: function ( /* optionalTarget */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .getControlPointsArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\treparametrizeByArcLength: function ( /* samplingCoef */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tfunction AxisHelper( size ) {\r\n\r\n\t\tconsole.warn( 'THREE.AxisHelper has been renamed to THREE.AxesHelper.' );\r\n\t\treturn new AxesHelper( size );\r\n\r\n\t}\r\n\r\n\tfunction BoundingBoxHelper( object, color ) {\r\n\r\n\t\tconsole.warn( 'THREE.BoundingBoxHelper has been deprecated. Creating a THREE.BoxHelper instead.' );\r\n\t\treturn new BoxHelper( object, color );\r\n\r\n\t}\r\n\r\n\tfunction EdgesHelper( object, hex ) {\r\n\r\n\t\tconsole.warn( 'THREE.EdgesHelper has been removed. Use THREE.EdgesGeometry instead.' );\r\n\t\treturn new LineSegments( new EdgesGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\r\n\r\n\t}\r\n\r\n\tGridHelper.prototype.setColors = function () {\r\n\r\n\t\tconsole.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' );\r\n\r\n\t};\r\n\r\n\tSkeletonHelper.prototype.update = function () {\r\n\r\n\t\tconsole.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' );\r\n\r\n\t};\r\n\r\n\tfunction WireframeHelper( object, hex ) {\r\n\r\n\t\tconsole.warn( 'THREE.WireframeHelper has been removed. Use THREE.WireframeGeometry instead.' );\r\n\t\treturn new LineSegments( new WireframeGeometry( object.geometry ), new LineBasicMaterial( { color: hex !== undefined ? hex : 0xffffff } ) );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tObject.assign( Loader.prototype, {\r\n\r\n\t\textractUrlBase: function ( url ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' );\r\n\t\t\treturn LoaderUtils.extractUrlBase( url );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tLoader.Handlers = {\r\n\r\n\t\tadd: function ( /* regex, loader */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Loader: Handlers.add() has been removed. Use LoadingManager.addHandler() instead.' );\r\n\r\n\t\t},\r\n\r\n\t\tget: function ( /* file */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Loader: Handlers.get() has been removed. Use LoadingManager.getHandler() instead.' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tfunction XHRLoader( manager ) {\r\n\r\n\t\tconsole.warn( 'THREE.XHRLoader has been renamed to THREE.FileLoader.' );\r\n\t\treturn new FileLoader( manager );\r\n\r\n\t}\r\n\r\n\tfunction BinaryTextureLoader( manager ) {\r\n\r\n\t\tconsole.warn( 'THREE.BinaryTextureLoader has been renamed to THREE.DataTextureLoader.' );\r\n\t\treturn new DataTextureLoader( manager );\r\n\r\n\t}\r\n\r\n\tObject.assign( ObjectLoader.prototype, {\r\n\r\n\t\tsetTexturePath: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );\r\n\t\t\treturn this.setResourcePath( value );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Box2.prototype, {\r\n\r\n\t\tcenter: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' );\r\n\t\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t\t},\r\n\t\tempty: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' );\r\n\t\t\treturn this.isEmpty();\r\n\r\n\t\t},\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tsize: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box2: .size() has been renamed to .getSize().' );\r\n\t\t\treturn this.getSize( optionalTarget );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.assign( Box3.prototype, {\r\n\r\n\t\tcenter: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' );\r\n\t\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t\t},\r\n\t\tempty: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' );\r\n\t\t\treturn this.isEmpty();\r\n\r\n\t\t},\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tisIntersectionSphere: function ( sphere ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\r\n\t\t\treturn this.intersectsSphere( sphere );\r\n\r\n\t\t},\r\n\t\tsize: function ( optionalTarget ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Box3: .size() has been renamed to .getSize().' );\r\n\t\t\treturn this.getSize( optionalTarget );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tLine3.prototype.center = function ( optionalTarget ) {\r\n\r\n\t\tconsole.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' );\r\n\t\treturn this.getCenter( optionalTarget );\r\n\r\n\t};\r\n\r\n\tObject.assign( _Math, {\r\n\r\n\t\trandom16: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' );\r\n\t\t\treturn Math.random();\r\n\r\n\t\t},\r\n\r\n\t\tnearestPowerOfTwo: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' );\r\n\t\t\treturn _Math.floorPowerOfTwo( value );\r\n\r\n\t\t},\r\n\r\n\t\tnextPowerOfTwo: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' );\r\n\t\t\treturn _Math.ceilPowerOfTwo( value );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Matrix3.prototype, {\r\n\r\n\t\tflattenToArrayOffset: function ( array, offset ) {\r\n\r\n\t\t\tconsole.warn( \"THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\r\n\t\t\treturn this.toArray( array, offset );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix3( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3Array: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\tapplyToBuffer: function ( buffer /*, offset, length */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\r\n\t\t\treturn this.applyToBufferAttribute( buffer );\r\n\r\n\t\t},\r\n\t\tapplyToVector3Array: function ( /* array, offset, length */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Matrix4.prototype, {\r\n\r\n\t\textractPosition: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' );\r\n\t\t\treturn this.copyPosition( m );\r\n\r\n\t\t},\r\n\t\tflattenToArrayOffset: function ( array, offset ) {\r\n\r\n\t\t\tconsole.warn( \"THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead.\" );\r\n\t\t\treturn this.toArray( array, offset );\r\n\r\n\t\t},\r\n\t\tgetPosition: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );\r\n\t\t\treturn new Vector3().setFromMatrixColumn( this, 3 );\r\n\r\n\t\t},\r\n\t\tsetRotationFromQuaternion: function ( q ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' );\r\n\t\t\treturn this.makeRotationFromQuaternion( q );\r\n\r\n\t\t},\r\n\t\tmultiplyToArray: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector4: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\tmultiplyVector3Array: function ( /* a */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateAxis: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' );\r\n\t\t\tv.transformDirection( this );\r\n\r\n\t\t},\r\n\t\tcrossVector: function ( vector ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' );\r\n\t\t\treturn vector.applyMatrix4( this );\r\n\r\n\t\t},\r\n\t\ttranslate: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .translate() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateX: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateX() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateY: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateY() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateZ: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateZ() has been removed.' );\r\n\r\n\t\t},\r\n\t\trotateByAxis: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' );\r\n\r\n\t\t},\r\n\t\tapplyToBuffer: function ( buffer /*, offset, length */ ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' );\r\n\t\t\treturn this.applyToBufferAttribute( buffer );\r\n\r\n\t\t},\r\n\t\tapplyToVector3Array: function ( /* array, offset, length */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' );\r\n\r\n\t\t},\r\n\t\tmakeFrustum: function ( left, right, bottom, top, near, far ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' );\r\n\t\t\treturn this.makePerspective( left, right, top, bottom, near, far );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tPlane.prototype.isIntersectionLine = function ( line ) {\r\n\r\n\t\tconsole.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' );\r\n\t\treturn this.intersectsLine( line );\r\n\r\n\t};\r\n\r\n\tQuaternion.prototype.multiplyVector3 = function ( vector ) {\r\n\r\n\t\tconsole.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' );\r\n\t\treturn vector.applyQuaternion( this );\r\n\r\n\t};\r\n\r\n\tObject.assign( Ray.prototype, {\r\n\r\n\t\tisIntersectionBox: function ( box ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' );\r\n\t\t\treturn this.intersectsBox( box );\r\n\r\n\t\t},\r\n\t\tisIntersectionPlane: function ( plane ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' );\r\n\t\t\treturn this.intersectsPlane( plane );\r\n\r\n\t\t},\r\n\t\tisIntersectionSphere: function ( sphere ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' );\r\n\t\t\treturn this.intersectsSphere( sphere );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle.prototype, {\r\n\r\n\t\tarea: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' );\r\n\t\t\treturn this.getArea();\r\n\r\n\t\t},\r\n\t\tbarycoordFromPoint: function ( point, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\r\n\t\t\treturn this.getBarycoord( point, target );\r\n\r\n\t\t},\r\n\t\tmidpoint: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' );\r\n\t\t\treturn this.getMidpoint( target );\r\n\r\n\t\t},\r\n\t\tnormal: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\r\n\t\t\treturn this.getNormal( target );\r\n\r\n\t\t},\r\n\t\tplane: function ( target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' );\r\n\t\t\treturn this.getPlane( target );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Triangle, {\r\n\r\n\t\tbarycoordFromPoint: function ( point, a, b, c, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' );\r\n\t\t\treturn Triangle.getBarycoord( point, a, b, c, target );\r\n\r\n\t\t},\r\n\t\tnormal: function ( a, b, c, target ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' );\r\n\t\t\treturn Triangle.getNormal( a, b, c, target );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Shape.prototype, {\r\n\r\n\t\textractAllPoints: function ( divisions ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' );\r\n\t\t\treturn this.extractPoints( divisions );\r\n\r\n\t\t},\r\n\t\textrude: function ( options ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' );\r\n\t\t\treturn new ExtrudeGeometry( this, options );\r\n\r\n\t\t},\r\n\t\tmakeGeometry: function ( options ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' );\r\n\t\t\treturn new ShapeGeometry( this, options );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector2.prototype, {\r\n\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tdistanceToManhattan: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\r\n\t\t\treturn this.manhattanDistanceTo( v );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector3.prototype, {\r\n\r\n\t\tsetEulerFromRotationMatrix: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' );\r\n\r\n\t\t},\r\n\t\tsetEulerFromQuaternion: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' );\r\n\r\n\t\t},\r\n\t\tgetPositionFromMatrix: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' );\r\n\t\t\treturn this.setFromMatrixPosition( m );\r\n\r\n\t\t},\r\n\t\tgetScaleFromMatrix: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' );\r\n\t\t\treturn this.setFromMatrixScale( m );\r\n\r\n\t\t},\r\n\t\tgetColumnFromMatrix: function ( index, matrix ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' );\r\n\t\t\treturn this.setFromMatrixColumn( matrix, index );\r\n\r\n\t\t},\r\n\t\tapplyProjection: function ( m ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' );\r\n\t\t\treturn this.applyMatrix4( m );\r\n\r\n\t\t},\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tdistanceToManhattan: function ( v ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' );\r\n\t\t\treturn this.manhattanDistanceTo( v );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Vector4.prototype, {\r\n\r\n\t\tfromAttribute: function ( attribute, index, offset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' );\r\n\t\t\treturn this.fromBufferAttribute( attribute, index, offset );\r\n\r\n\t\t},\r\n\t\tlengthManhattan: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' );\r\n\t\t\treturn this.manhattanLength();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( Geometry.prototype, {\r\n\r\n\t\tcomputeTangents: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Geometry: .computeTangents() has been removed.' );\r\n\r\n\t\t},\r\n\t\tcomputeLineDistances: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Object3D.prototype, {\r\n\r\n\t\tgetChildByName: function ( name ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' );\r\n\t\t\treturn this.getObjectByName( name );\r\n\r\n\t\t},\r\n\t\trenderDepth: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' );\r\n\r\n\t\t},\r\n\t\ttranslate: function ( distance, axis ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' );\r\n\t\t\treturn this.translateOnAxis( axis, distance );\r\n\r\n\t\t},\r\n\t\tgetWorldRotation: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Object3D.prototype, {\r\n\r\n\t\teulerOrder: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\r\n\t\t\t\treturn this.rotation.order;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' );\r\n\t\t\t\tthis.rotation.order = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tuseQuaternion: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( Mesh.prototype, {\r\n\r\n\t\tsetDrawMode: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.Mesh: .setDrawMode() has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );\r\n\r\n\t\t},\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( Mesh.prototype, {\r\n\r\n\t\tdrawMode: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode.' );\r\n\t\t\t\treturn TrianglesDrawMode;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.Mesh: .drawMode has been removed. The renderer now always assumes THREE.TrianglesDrawMode. Transform your geometry via BufferGeometryUtils.toTrianglesDrawMode() if necessary.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( LOD.prototype, {\r\n\r\n\t\tobjects: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.LOD: .objects has been renamed to .levels.' );\r\n\t\t\t\treturn this.levels;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperty( Skeleton.prototype, 'useVertexTexture', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\r\n\r\n\t\t},\r\n\t\tset: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Skeleton: useVertexTexture has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tSkinnedMesh.prototype.initBones = function () {\r\n\r\n\t\tconsole.error( 'THREE.SkinnedMesh: initBones() has been removed.' );\r\n\r\n\t};\r\n\r\n\tObject.defineProperty( Curve.prototype, '__arcLengthDivisions', {\r\n\r\n\t\tget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\r\n\t\t\treturn this.arcLengthDivisions;\r\n\r\n\t\t},\r\n\t\tset: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' );\r\n\t\t\tthis.arcLengthDivisions = value;\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tPerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) {\r\n\r\n\t\tconsole.warn( \"THREE.PerspectiveCamera.setLens is deprecated. \" +\r\n\t\t\t\t\"Use .setFocalLength and .filmGauge for a photographic setup.\" );\r\n\r\n\t\tif ( filmGauge !== undefined ) { this.filmGauge = filmGauge; }\r\n\t\tthis.setFocalLength( focalLength );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Light.prototype, {\r\n\t\tonlyShadow: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .onlyShadow has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraFov: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' );\r\n\t\t\t\tthis.shadow.camera.fov = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraLeft: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' );\r\n\t\t\t\tthis.shadow.camera.left = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraRight: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' );\r\n\t\t\t\tthis.shadow.camera.right = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraTop: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' );\r\n\t\t\t\tthis.shadow.camera.top = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraBottom: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' );\r\n\t\t\t\tthis.shadow.camera.bottom = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraNear: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' );\r\n\t\t\t\tthis.shadow.camera.near = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraFar: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' );\r\n\t\t\t\tthis.shadow.camera.far = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowCameraVisible: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowBias: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' );\r\n\t\t\t\tthis.shadow.bias = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowDarkness: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowDarkness has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapWidth: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' );\r\n\t\t\t\tthis.shadow.mapSize.width = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapHeight: {\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' );\r\n\t\t\t\tthis.shadow.mapSize.height = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( BufferAttribute.prototype, {\r\n\r\n\t\tlength: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' );\r\n\t\t\t\treturn this.array.length;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tdynamic: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );\r\n\t\t\t\treturn this.usage === DynamicDrawUsage;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute: .dynamic has been deprecated. Use .usage instead.' );\r\n\t\t\t\tthis.setUsage( DynamicDrawUsage );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( BufferAttribute.prototype, {\r\n\t\tsetDynamic: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferAttribute: .setDynamic() has been deprecated. Use .setUsage() instead.' );\r\n\t\t\tthis.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\t\tcopyIndicesArray: function ( /* indices */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetArray: function ( /* array */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.BufferAttribute: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.assign( BufferGeometry.prototype, {\r\n\r\n\t\taddIndex: function ( index ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' );\r\n\t\t\tthis.setIndex( index );\r\n\r\n\t\t},\r\n\t\taddAttribute: function ( name, attribute ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addAttribute() has been renamed to .setAttribute().' );\r\n\r\n\t\t\tif ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' );\r\n\r\n\t\t\t\treturn this.setAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( name === 'index' ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' );\r\n\t\t\t\tthis.setIndex( attribute );\r\n\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn this.setAttribute( name, attribute );\r\n\r\n\t\t},\r\n\t\taddDrawCall: function ( start, count, indexOffset ) {\r\n\r\n\t\t\tif ( indexOffset !== undefined ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' );\r\n\r\n\t\t\t}\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' );\r\n\t\t\tthis.addGroup( start, count );\r\n\r\n\t\t},\r\n\t\tclearDrawCalls: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' );\r\n\t\t\tthis.clearGroups();\r\n\r\n\t\t},\r\n\t\tcomputeTangents: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' );\r\n\r\n\t\t},\r\n\t\tcomputeOffsets: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' );\r\n\r\n\t\t},\r\n\t\tremoveAttribute: function ( name ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.BufferGeometry: .removeAttribute() has been renamed to .deleteAttribute().' );\r\n\r\n\t\t\treturn this.deleteAttribute( name );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\tObject.defineProperties( BufferGeometry.prototype, {\r\n\r\n\t\tdrawcalls: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' );\r\n\t\t\t\treturn this.groups;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\toffsets: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' );\r\n\t\t\t\treturn this.groups;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( InterleavedBuffer.prototype, {\r\n\r\n\t\tdynamic: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );\r\n\t\t\t\treturn this.usage === DynamicDrawUsage;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .length has been deprecated. Use .usage instead.' );\r\n\t\t\t\tthis.setUsage( value );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.assign( InterleavedBuffer.prototype, {\r\n\t\tsetDynamic: function ( value ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.InterleavedBuffer: .setDynamic() has been deprecated. Use .setUsage() instead.' );\r\n\t\t\tthis.setUsage( value === true ? DynamicDrawUsage : StaticDrawUsage );\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\t\tsetArray: function ( /* array */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.InterleavedBuffer: .setArray has been removed. Use BufferGeometry .setAttribute to replace/resize attribute buffers' );\r\n\r\n\t\t}\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( ExtrudeBufferGeometry.prototype, {\r\n\r\n\t\tgetArrays: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' );\r\n\r\n\t\t},\r\n\r\n\t\taddShapeList: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' );\r\n\r\n\t\t},\r\n\r\n\t\taddShape: function () {\r\n\r\n\t\t\tconsole.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Uniform.prototype, {\r\n\r\n\t\tdynamic: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tonUpdate: {\r\n\t\t\tvalue: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Material.prototype, {\r\n\r\n\t\twrapAround: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapAround has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\toverdraw: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .overdraw has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\twrapRGB: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Material: .wrapRGB has been removed.' );\r\n\t\t\t\treturn new Color();\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tshading: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\r\n\t\t\t\tthis.flatShading = ( value === FlatShading );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\r\n\t\tstencilMask: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );\r\n\t\t\t\treturn this.stencilFuncMask;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );\r\n\t\t\t\tthis.stencilFuncMask = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( MeshPhongMaterial.prototype, {\r\n\r\n\t\tmetal: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( ShaderMaterial.prototype, {\r\n\r\n\t\tderivatives: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\r\n\t\t\t\treturn this.extensions.derivatives;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' );\r\n\t\t\t\tthis.extensions.derivatives = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.assign( WebGLRenderer.prototype, {\r\n\r\n\t\tclearTarget: function ( renderTarget, color, depth, stencil ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .clearTarget() has been deprecated. Use .setRenderTarget() and .clear() instead.' );\r\n\t\t\tthis.setRenderTarget( renderTarget );\r\n\t\t\tthis.clear( color, depth, stencil );\r\n\r\n\t\t},\r\n\t\tanimate: function ( callback ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' );\r\n\t\t\tthis.setAnimationLoop( callback );\r\n\r\n\t\t},\r\n\t\tgetCurrentRenderTarget: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' );\r\n\t\t\treturn this.getRenderTarget();\r\n\r\n\t\t},\r\n\t\tgetMaxAnisotropy: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' );\r\n\t\t\treturn this.capabilities.getMaxAnisotropy();\r\n\r\n\t\t},\r\n\t\tgetPrecision: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' );\r\n\t\t\treturn this.capabilities.precision;\r\n\r\n\t\t},\r\n\t\tresetGLState: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' );\r\n\t\t\treturn this.state.reset();\r\n\r\n\t\t},\r\n\t\tsupportsFloatTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \\'OES_texture_float\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_texture_float' );\r\n\r\n\t\t},\r\n\t\tsupportsHalfFloatTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \\'OES_texture_half_float\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_texture_half_float' );\r\n\r\n\t\t},\r\n\t\tsupportsStandardDerivatives: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \\'OES_standard_derivatives\\' ).' );\r\n\t\t\treturn this.extensions.get( 'OES_standard_derivatives' );\r\n\r\n\t\t},\r\n\t\tsupportsCompressedTextureS3TC: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \\'WEBGL_compressed_texture_s3tc\\' ).' );\r\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_s3tc' );\r\n\r\n\t\t},\r\n\t\tsupportsCompressedTexturePVRTC: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \\'WEBGL_compressed_texture_pvrtc\\' ).' );\r\n\t\t\treturn this.extensions.get( 'WEBGL_compressed_texture_pvrtc' );\r\n\r\n\t\t},\r\n\t\tsupportsBlendMinMax: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \\'EXT_blend_minmax\\' ).' );\r\n\t\t\treturn this.extensions.get( 'EXT_blend_minmax' );\r\n\r\n\t\t},\r\n\t\tsupportsVertexTextures: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' );\r\n\t\t\treturn this.capabilities.vertexTextures;\r\n\r\n\t\t},\r\n\t\tsupportsInstancedArrays: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \\'ANGLE_instanced_arrays\\' ).' );\r\n\t\t\treturn this.extensions.get( 'ANGLE_instanced_arrays' );\r\n\r\n\t\t},\r\n\t\tenableScissorTest: function ( boolean ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' );\r\n\t\t\tthis.setScissorTest( boolean );\r\n\r\n\t\t},\r\n\t\tinitMaterial: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' );\r\n\r\n\t\t},\r\n\t\taddPrePlugin: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' );\r\n\r\n\t\t},\r\n\t\taddPostPlugin: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' );\r\n\r\n\t\t},\r\n\t\tupdateShadowMap: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetFaceCulling: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' );\r\n\r\n\t\t},\r\n\t\tallocTextureUnit: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .allocTextureUnit() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetTexture: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setTexture() has been removed.' );\r\n\r\n\t\t},\r\n\t\tsetTextureCube: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .setTextureCube() has been removed.' );\r\n\r\n\t\t},\r\n\t\tgetActiveMipMapLevel: function () {\r\n\r\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: .getActiveMipMapLevel() is now .getActiveMipmapLevel().' );\r\n\t\t\treturn this.getActiveMipmapLevel();\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( WebGLRenderer.prototype, {\r\n\r\n\t\tshadowMapEnabled: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.shadowMap.enabled;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' );\r\n\t\t\t\tthis.shadowMap.enabled = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapType: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\treturn this.shadowMap.type;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' );\r\n\t\t\t\tthis.shadowMap.type = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tshadowMapCullFace: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tcontext: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .context has been removed. Use .getContext() instead.' );\r\n\t\t\t\treturn this.getContext();\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tvr: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .vr has been removed. Use .xr instead.' );\r\n\t\t\t\treturn this.xr;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tgammaInput: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Please define the correct color spaces for textures via Texture.encoding instead.' );\r\n\t\t\t\treturn false;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .gammaInput has been removed. Please define the correct color spaces for textures via Texture.encoding instead.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tObject.defineProperties( WebGLShadowMap.prototype, {\r\n\r\n\t\tcullFace: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( /* cullFace */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trenderReverseSided: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trenderSingleSided: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\r\n\t\t\t\treturn undefined;\r\n\r\n\t\t\t},\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebGLRenderTargetCube.prototype, {\r\n\r\n\t\tactiveCubeFace: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeCubeFace has been removed. It is now the second parameter of WebGLRenderer.setRenderTarget().' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tactiveMipMapLevel: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTargetCube: .activeMipMapLevel has been removed. It is now the third parameter of WebGLRenderer.setRenderTarget().' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebGLRenderTarget.prototype, {\r\n\r\n\t\twrapS: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\r\n\t\t\t\treturn this.texture.wrapS;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' );\r\n\t\t\t\tthis.texture.wrapS = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\twrapT: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\r\n\t\t\t\treturn this.texture.wrapT;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' );\r\n\t\t\t\tthis.texture.wrapT = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tmagFilter: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\r\n\t\t\t\treturn this.texture.magFilter;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' );\r\n\t\t\t\tthis.texture.magFilter = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tminFilter: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\r\n\t\t\t\treturn this.texture.minFilter;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' );\r\n\t\t\t\tthis.texture.minFilter = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tanisotropy: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\r\n\t\t\t\treturn this.texture.anisotropy;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' );\r\n\t\t\t\tthis.texture.anisotropy = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\toffset: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\r\n\t\t\t\treturn this.texture.offset;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' );\r\n\t\t\t\tthis.texture.offset = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\trepeat: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\r\n\t\t\t\treturn this.texture.repeat;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' );\r\n\t\t\t\tthis.texture.repeat = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tformat: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\r\n\t\t\t\treturn this.texture.format;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' );\r\n\t\t\t\tthis.texture.format = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\ttype: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\r\n\t\t\t\treturn this.texture.type;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' );\r\n\t\t\t\tthis.texture.type = value;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tgenerateMipmaps: {\r\n\t\t\tget: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\r\n\t\t\t\treturn this.texture.generateMipmaps;\r\n\r\n\t\t\t},\r\n\t\t\tset: function ( value ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' );\r\n\t\t\t\tthis.texture.generateMipmaps = value;\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( WebVRManager.prototype, {\r\n\r\n\t\tstanding: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .standing has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tuserHeight: {\r\n\t\t\tset: function ( /* value */ ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.WebVRManager: .userHeight has been removed.' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t//\r\n\r\n\tObject.defineProperties( Audio.prototype, {\r\n\r\n\t\tload: {\r\n\t\t\tvalue: function ( file ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' );\r\n\t\t\t\tvar scope = this;\r\n\t\t\t\tvar audioLoader = new AudioLoader();\r\n\t\t\t\taudioLoader.load( file, function ( buffer ) {\r\n\r\n\t\t\t\t\tscope.setBuffer( buffer );\r\n\r\n\t\t\t\t} );\r\n\t\t\t\treturn this;\r\n\r\n\t\t\t}\r\n\t\t},\r\n\t\tstartTime: {\r\n\t\t\tset: function () {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.Audio: .startTime is now .play( delay ).' );\r\n\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\tAudioAnalyser.prototype.getData = function () {\r\n\r\n\t\tconsole.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' );\r\n\t\treturn this.getFrequencyData();\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tCubeCamera.prototype.updateCubeMap = function ( renderer, scene ) {\r\n\r\n\t\tconsole.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' );\r\n\t\treturn this.update( renderer, scene );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar GeometryUtils = {\r\n\r\n\t\tmerge: function ( geometry1, geometry2, materialIndexOffset ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );\r\n\t\t\tvar matrix;\r\n\r\n\t\t\tif ( geometry2.isMesh ) {\r\n\r\n\t\t\t\tgeometry2.matrixAutoUpdate && geometry2.updateMatrix();\r\n\r\n\t\t\t\tmatrix = geometry2.matrix;\r\n\t\t\t\tgeometry2 = geometry2.geometry;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry1.merge( geometry2, matrix, materialIndexOffset );\r\n\r\n\t\t},\r\n\r\n\t\tcenter: function ( geometry ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );\r\n\t\t\treturn geometry.center();\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tImageUtils.crossOrigin = undefined;\r\n\r\n\tImageUtils.loadTexture = function ( url, mapping, onLoad, onError ) {\r\n\r\n\t\tconsole.warn( 'THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.' );\r\n\r\n\t\tvar loader = new TextureLoader();\r\n\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\tvar texture = loader.load( url, onLoad, undefined, onError );\r\n\r\n\t\tif ( mapping ) { texture.mapping = mapping; }\r\n\r\n\t\treturn texture;\r\n\r\n\t};\r\n\r\n\tImageUtils.loadTextureCube = function ( urls, mapping, onLoad, onError ) {\r\n\r\n\t\tconsole.warn( 'THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.' );\r\n\r\n\t\tvar loader = new CubeTextureLoader();\r\n\t\tloader.setCrossOrigin( this.crossOrigin );\r\n\r\n\t\tvar texture = loader.load( urls, onLoad, undefined, onError );\r\n\r\n\t\tif ( mapping ) { texture.mapping = mapping; }\r\n\r\n\t\treturn texture;\r\n\r\n\t};\r\n\r\n\tImageUtils.loadCompressedTexture = function () {\r\n\r\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.' );\r\n\r\n\t};\r\n\r\n\tImageUtils.loadCompressedTextureCube = function () {\r\n\r\n\t\tconsole.error( 'THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.' );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction CanvasRenderer() {\r\n\r\n\t\tconsole.error( 'THREE.CanvasRenderer has been removed' );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tfunction JSONLoader() {\r\n\r\n\t\tconsole.error( 'THREE.JSONLoader has been removed.' );\r\n\r\n\t}\r\n\r\n\t//\r\n\r\n\tvar SceneUtils = {\r\n\r\n\t\tcreateMultiMaterialObject: function ( /* geometry, materials */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t},\r\n\r\n\t\tdetach: function ( /* child, parent, scene */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t},\r\n\r\n\t\tattach: function ( /* child, scene, parent */ ) {\r\n\r\n\t\t\tconsole.error( 'THREE.SceneUtils has been moved to /examples/js/utils/SceneUtils.js' );\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tfunction LensFlare() {\r\n\r\n\t\tconsole.error( 'THREE.LensFlare has been moved to /examples/js/objects/Lensflare.js' );\r\n\r\n\t}\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\r\n\r\n\t\t/* eslint-disable no-undef */\r\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {\r\n\t\t\trevision: REVISION,\r\n\t\t} } ) );\r\n\t\t/* eslint-enable no-undef */\r\n\r\n\t}\n\n\texports.ACESFilmicToneMapping = ACESFilmicToneMapping;\n\texports.AddEquation = AddEquation;\n\texports.AddOperation = AddOperation;\n\texports.AdditiveBlending = AdditiveBlending;\n\texports.AlphaFormat = AlphaFormat;\n\texports.AlwaysDepth = AlwaysDepth;\n\texports.AlwaysStencilFunc = AlwaysStencilFunc;\n\texports.AmbientLight = AmbientLight;\n\texports.AmbientLightProbe = AmbientLightProbe;\n\texports.AnimationClip = AnimationClip;\n\texports.AnimationLoader = AnimationLoader;\n\texports.AnimationMixer = AnimationMixer;\n\texports.AnimationObjectGroup = AnimationObjectGroup;\n\texports.AnimationUtils = AnimationUtils;\n\texports.ArcCurve = ArcCurve;\n\texports.ArrayCamera = ArrayCamera;\n\texports.ArrowHelper = ArrowHelper;\n\texports.Audio = Audio;\n\texports.AudioAnalyser = AudioAnalyser;\n\texports.AudioContext = AudioContext;\n\texports.AudioListener = AudioListener;\n\texports.AudioLoader = AudioLoader;\n\texports.AxesHelper = AxesHelper;\n\texports.AxisHelper = AxisHelper;\n\texports.BackSide = BackSide;\n\texports.BasicDepthPacking = BasicDepthPacking;\n\texports.BasicShadowMap = BasicShadowMap;\n\texports.BinaryTextureLoader = BinaryTextureLoader;\n\texports.Bone = Bone;\n\texports.BooleanKeyframeTrack = BooleanKeyframeTrack;\n\texports.BoundingBoxHelper = BoundingBoxHelper;\n\texports.Box2 = Box2;\n\texports.Box3 = Box3;\n\texports.Box3Helper = Box3Helper;\n\texports.BoxBufferGeometry = BoxBufferGeometry;\n\texports.BoxGeometry = BoxGeometry;\n\texports.BoxHelper = BoxHelper;\n\texports.BufferAttribute = BufferAttribute;\n\texports.BufferGeometry = BufferGeometry;\n\texports.BufferGeometryLoader = BufferGeometryLoader;\n\texports.ByteType = ByteType;\n\texports.Cache = Cache;\n\texports.Camera = Camera;\n\texports.CameraHelper = CameraHelper;\n\texports.CanvasRenderer = CanvasRenderer;\n\texports.CanvasTexture = CanvasTexture;\n\texports.CatmullRomCurve3 = CatmullRomCurve3;\n\texports.CineonToneMapping = CineonToneMapping;\n\texports.CircleBufferGeometry = CircleBufferGeometry;\n\texports.CircleGeometry = CircleGeometry;\n\texports.ClampToEdgeWrapping = ClampToEdgeWrapping;\n\texports.Clock = Clock;\n\texports.ClosedSplineCurve3 = ClosedSplineCurve3;\n\texports.Color = Color;\n\texports.ColorKeyframeTrack = ColorKeyframeTrack;\n\texports.CompressedTexture = CompressedTexture;\n\texports.CompressedTextureLoader = CompressedTextureLoader;\n\texports.ConeBufferGeometry = ConeBufferGeometry;\n\texports.ConeGeometry = ConeGeometry;\n\texports.CubeCamera = CubeCamera;\n\texports.CubeGeometry = BoxGeometry;\n\texports.CubeReflectionMapping = CubeReflectionMapping;\n\texports.CubeRefractionMapping = CubeRefractionMapping;\n\texports.CubeTexture = CubeTexture;\n\texports.CubeTextureLoader = CubeTextureLoader;\n\texports.CubeUVReflectionMapping = CubeUVReflectionMapping;\n\texports.CubeUVRefractionMapping = CubeUVRefractionMapping;\n\texports.CubicBezierCurve = CubicBezierCurve;\n\texports.CubicBezierCurve3 = CubicBezierCurve3;\n\texports.CubicInterpolant = CubicInterpolant;\n\texports.CullFaceBack = CullFaceBack;\n\texports.CullFaceFront = CullFaceFront;\n\texports.CullFaceFrontBack = CullFaceFrontBack;\n\texports.CullFaceNone = CullFaceNone;\n\texports.Curve = Curve;\n\texports.CurvePath = CurvePath;\n\texports.CustomBlending = CustomBlending;\n\texports.CylinderBufferGeometry = CylinderBufferGeometry;\n\texports.CylinderGeometry = CylinderGeometry;\n\texports.Cylindrical = Cylindrical;\n\texports.DataTexture = DataTexture;\n\texports.DataTexture2DArray = DataTexture2DArray;\n\texports.DataTexture3D = DataTexture3D;\n\texports.DataTextureLoader = DataTextureLoader;\n\texports.DecrementStencilOp = DecrementStencilOp;\n\texports.DecrementWrapStencilOp = DecrementWrapStencilOp;\n\texports.DefaultLoadingManager = DefaultLoadingManager;\n\texports.DepthFormat = DepthFormat;\n\texports.DepthStencilFormat = DepthStencilFormat;\n\texports.DepthTexture = DepthTexture;\n\texports.DirectionalLight = DirectionalLight;\n\texports.DirectionalLightHelper = DirectionalLightHelper;\n\texports.DirectionalLightShadow = DirectionalLightShadow;\n\texports.DiscreteInterpolant = DiscreteInterpolant;\n\texports.DodecahedronBufferGeometry = DodecahedronBufferGeometry;\n\texports.DodecahedronGeometry = DodecahedronGeometry;\n\texports.DoubleSide = DoubleSide;\n\texports.DstAlphaFactor = DstAlphaFactor;\n\texports.DstColorFactor = DstColorFactor;\n\texports.DynamicBufferAttribute = DynamicBufferAttribute;\n\texports.DynamicCopyUsage = DynamicCopyUsage;\n\texports.DynamicDrawUsage = DynamicDrawUsage;\n\texports.DynamicReadUsage = DynamicReadUsage;\n\texports.EdgesGeometry = EdgesGeometry;\n\texports.EdgesHelper = EdgesHelper;\n\texports.EllipseCurve = EllipseCurve;\n\texports.EqualDepth = EqualDepth;\n\texports.EqualStencilFunc = EqualStencilFunc;\n\texports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;\n\texports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;\n\texports.Euler = Euler;\n\texports.EventDispatcher = EventDispatcher;\n\texports.ExtrudeBufferGeometry = ExtrudeBufferGeometry;\n\texports.ExtrudeGeometry = ExtrudeGeometry;\n\texports.Face3 = Face3;\n\texports.Face4 = Face4;\n\texports.FaceColors = FaceColors;\n\texports.FaceNormalsHelper = FaceNormalsHelper;\n\texports.FileLoader = FileLoader;\n\texports.FlatShading = FlatShading;\n\texports.Float32Attribute = Float32Attribute;\n\texports.Float32BufferAttribute = Float32BufferAttribute;\n\texports.Float64Attribute = Float64Attribute;\n\texports.Float64BufferAttribute = Float64BufferAttribute;\n\texports.FloatType = FloatType;\n\texports.Fog = Fog;\n\texports.FogExp2 = FogExp2;\n\texports.Font = Font;\n\texports.FontLoader = FontLoader;\n\texports.FrontFaceDirectionCCW = FrontFaceDirectionCCW;\n\texports.FrontFaceDirectionCW = FrontFaceDirectionCW;\n\texports.FrontSide = FrontSide;\n\texports.Frustum = Frustum;\n\texports.GammaEncoding = GammaEncoding;\n\texports.Geometry = Geometry;\n\texports.GeometryUtils = GeometryUtils;\n\texports.GreaterDepth = GreaterDepth;\n\texports.GreaterEqualDepth = GreaterEqualDepth;\n\texports.GreaterEqualStencilFunc = GreaterEqualStencilFunc;\n\texports.GreaterStencilFunc = GreaterStencilFunc;\n\texports.GridHelper = GridHelper;\n\texports.Group = Group;\n\texports.HalfFloatType = HalfFloatType;\n\texports.HemisphereLight = HemisphereLight;\n\texports.HemisphereLightHelper = HemisphereLightHelper;\n\texports.HemisphereLightProbe = HemisphereLightProbe;\n\texports.IcosahedronBufferGeometry = IcosahedronBufferGeometry;\n\texports.IcosahedronGeometry = IcosahedronGeometry;\n\texports.ImageBitmapLoader = ImageBitmapLoader;\n\texports.ImageLoader = ImageLoader;\n\texports.ImageUtils = ImageUtils;\n\texports.ImmediateRenderObject = ImmediateRenderObject;\n\texports.IncrementStencilOp = IncrementStencilOp;\n\texports.IncrementWrapStencilOp = IncrementWrapStencilOp;\n\texports.InstancedBufferAttribute = InstancedBufferAttribute;\n\texports.InstancedBufferGeometry = InstancedBufferGeometry;\n\texports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;\n\texports.InstancedMesh = InstancedMesh;\n\texports.Int16Attribute = Int16Attribute;\n\texports.Int16BufferAttribute = Int16BufferAttribute;\n\texports.Int32Attribute = Int32Attribute;\n\texports.Int32BufferAttribute = Int32BufferAttribute;\n\texports.Int8Attribute = Int8Attribute;\n\texports.Int8BufferAttribute = Int8BufferAttribute;\n\texports.IntType = IntType;\n\texports.InterleavedBuffer = InterleavedBuffer;\n\texports.InterleavedBufferAttribute = InterleavedBufferAttribute;\n\texports.Interpolant = Interpolant;\n\texports.InterpolateDiscrete = InterpolateDiscrete;\n\texports.InterpolateLinear = InterpolateLinear;\n\texports.InterpolateSmooth = InterpolateSmooth;\n\texports.InvertStencilOp = InvertStencilOp;\n\texports.JSONLoader = JSONLoader;\n\texports.KeepStencilOp = KeepStencilOp;\n\texports.KeyframeTrack = KeyframeTrack;\n\texports.LOD = LOD;\n\texports.LatheBufferGeometry = LatheBufferGeometry;\n\texports.LatheGeometry = LatheGeometry;\n\texports.Layers = Layers;\n\texports.LensFlare = LensFlare;\n\texports.LessDepth = LessDepth;\n\texports.LessEqualDepth = LessEqualDepth;\n\texports.LessEqualStencilFunc = LessEqualStencilFunc;\n\texports.LessStencilFunc = LessStencilFunc;\n\texports.Light = Light;\n\texports.LightProbe = LightProbe;\n\texports.LightProbeHelper = LightProbeHelper;\n\texports.LightShadow = LightShadow;\n\texports.Line = Line;\n\texports.Line3 = Line3;\n\texports.LineBasicMaterial = LineBasicMaterial;\n\texports.LineCurve = LineCurve;\n\texports.LineCurve3 = LineCurve3;\n\texports.LineDashedMaterial = LineDashedMaterial;\n\texports.LineLoop = LineLoop;\n\texports.LinePieces = LinePieces;\n\texports.LineSegments = LineSegments;\n\texports.LineStrip = LineStrip;\n\texports.LinearEncoding = LinearEncoding;\n\texports.LinearFilter = LinearFilter;\n\texports.LinearInterpolant = LinearInterpolant;\n\texports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;\n\texports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;\n\texports.LinearMipmapLinearFilter = LinearMipmapLinearFilter;\n\texports.LinearMipmapNearestFilter = LinearMipmapNearestFilter;\n\texports.LinearToneMapping = LinearToneMapping;\n\texports.Loader = Loader;\n\texports.LoaderUtils = LoaderUtils;\n\texports.LoadingManager = LoadingManager;\n\texports.LogLuvEncoding = LogLuvEncoding;\n\texports.LoopOnce = LoopOnce;\n\texports.LoopPingPong = LoopPingPong;\n\texports.LoopRepeat = LoopRepeat;\n\texports.LuminanceAlphaFormat = LuminanceAlphaFormat;\n\texports.LuminanceFormat = LuminanceFormat;\n\texports.MOUSE = MOUSE;\n\texports.Material = Material;\n\texports.MaterialLoader = MaterialLoader;\n\texports.Math = _Math;\n\texports.Matrix3 = Matrix3;\n\texports.Matrix4 = Matrix4;\n\texports.MaxEquation = MaxEquation;\n\texports.Mesh = Mesh;\n\texports.MeshBasicMaterial = MeshBasicMaterial;\n\texports.MeshDepthMaterial = MeshDepthMaterial;\n\texports.MeshDistanceMaterial = MeshDistanceMaterial;\n\texports.MeshFaceMaterial = MeshFaceMaterial;\n\texports.MeshLambertMaterial = MeshLambertMaterial;\n\texports.MeshMatcapMaterial = MeshMatcapMaterial;\n\texports.MeshNormalMaterial = MeshNormalMaterial;\n\texports.MeshPhongMaterial = MeshPhongMaterial;\n\texports.MeshPhysicalMaterial = MeshPhysicalMaterial;\n\texports.MeshStandardMaterial = MeshStandardMaterial;\n\texports.MeshToonMaterial = MeshToonMaterial;\n\texports.MinEquation = MinEquation;\n\texports.MirroredRepeatWrapping = MirroredRepeatWrapping;\n\texports.MixOperation = MixOperation;\n\texports.MultiMaterial = MultiMaterial;\n\texports.MultiplyBlending = MultiplyBlending;\n\texports.MultiplyOperation = MultiplyOperation;\n\texports.NearestFilter = NearestFilter;\n\texports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;\n\texports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;\n\texports.NearestMipmapLinearFilter = NearestMipmapLinearFilter;\n\texports.NearestMipmapNearestFilter = NearestMipmapNearestFilter;\n\texports.NeverDepth = NeverDepth;\n\texports.NeverStencilFunc = NeverStencilFunc;\n\texports.NoBlending = NoBlending;\n\texports.NoColors = NoColors;\n\texports.NoToneMapping = NoToneMapping;\n\texports.NormalBlending = NormalBlending;\n\texports.NotEqualDepth = NotEqualDepth;\n\texports.NotEqualStencilFunc = NotEqualStencilFunc;\n\texports.NumberKeyframeTrack = NumberKeyframeTrack;\n\texports.Object3D = Object3D;\n\texports.ObjectLoader = ObjectLoader;\n\texports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;\n\texports.OctahedronBufferGeometry = OctahedronBufferGeometry;\n\texports.OctahedronGeometry = OctahedronGeometry;\n\texports.OneFactor = OneFactor;\n\texports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;\n\texports.OneMinusDstColorFactor = OneMinusDstColorFactor;\n\texports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;\n\texports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;\n\texports.OrthographicCamera = OrthographicCamera;\n\texports.PCFShadowMap = PCFShadowMap;\n\texports.PCFSoftShadowMap = PCFSoftShadowMap;\n\texports.ParametricBufferGeometry = ParametricBufferGeometry;\n\texports.ParametricGeometry = ParametricGeometry;\n\texports.Particle = Particle;\n\texports.ParticleBasicMaterial = ParticleBasicMaterial;\n\texports.ParticleSystem = ParticleSystem;\n\texports.ParticleSystemMaterial = ParticleSystemMaterial;\n\texports.Path = Path;\n\texports.PerspectiveCamera = PerspectiveCamera;\n\texports.Plane = Plane;\n\texports.PlaneBufferGeometry = PlaneBufferGeometry;\n\texports.PlaneGeometry = PlaneGeometry;\n\texports.PlaneHelper = PlaneHelper;\n\texports.PointCloud = PointCloud;\n\texports.PointCloudMaterial = PointCloudMaterial;\n\texports.PointLight = PointLight;\n\texports.PointLightHelper = PointLightHelper;\n\texports.Points = Points;\n\texports.PointsMaterial = PointsMaterial;\n\texports.PolarGridHelper = PolarGridHelper;\n\texports.PolyhedronBufferGeometry = PolyhedronBufferGeometry;\n\texports.PolyhedronGeometry = PolyhedronGeometry;\n\texports.PositionalAudio = PositionalAudio;\n\texports.PositionalAudioHelper = PositionalAudioHelper;\n\texports.PropertyBinding = PropertyBinding;\n\texports.PropertyMixer = PropertyMixer;\n\texports.QuadraticBezierCurve = QuadraticBezierCurve;\n\texports.QuadraticBezierCurve3 = QuadraticBezierCurve3;\n\texports.Quaternion = Quaternion;\n\texports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;\n\texports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;\n\texports.REVISION = REVISION;\n\texports.RGBADepthPacking = RGBADepthPacking;\n\texports.RGBAFormat = RGBAFormat;\n\texports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;\n\texports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;\n\texports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;\n\texports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;\n\texports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;\n\texports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;\n\texports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;\n\texports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;\n\texports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;\n\texports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;\n\texports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;\n\texports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;\n\texports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;\n\texports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;\n\texports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;\n\texports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;\n\texports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;\n\texports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;\n\texports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;\n\texports.RGBDEncoding = RGBDEncoding;\n\texports.RGBEEncoding = RGBEEncoding;\n\texports.RGBEFormat = RGBEFormat;\n\texports.RGBFormat = RGBFormat;\n\texports.RGBM16Encoding = RGBM16Encoding;\n\texports.RGBM7Encoding = RGBM7Encoding;\n\texports.RGB_ETC1_Format = RGB_ETC1_Format;\n\texports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;\n\texports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;\n\texports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;\n\texports.RawShaderMaterial = RawShaderMaterial;\n\texports.Ray = Ray;\n\texports.Raycaster = Raycaster;\n\texports.RectAreaLight = RectAreaLight;\n\texports.RectAreaLightHelper = RectAreaLightHelper;\n\texports.RedFormat = RedFormat;\n\texports.ReinhardToneMapping = ReinhardToneMapping;\n\texports.RepeatWrapping = RepeatWrapping;\n\texports.ReplaceStencilOp = ReplaceStencilOp;\n\texports.ReverseSubtractEquation = ReverseSubtractEquation;\n\texports.RingBufferGeometry = RingBufferGeometry;\n\texports.RingGeometry = RingGeometry;\n\texports.Scene = Scene;\n\texports.SceneUtils = SceneUtils;\n\texports.ShaderChunk = ShaderChunk;\n\texports.ShaderLib = ShaderLib;\n\texports.ShaderMaterial = ShaderMaterial;\n\texports.ShadowMaterial = ShadowMaterial;\n\texports.Shape = Shape;\n\texports.ShapeBufferGeometry = ShapeBufferGeometry;\n\texports.ShapeGeometry = ShapeGeometry;\n\texports.ShapePath = ShapePath;\n\texports.ShapeUtils = ShapeUtils;\n\texports.ShortType = ShortType;\n\texports.Skeleton = Skeleton;\n\texports.SkeletonHelper = SkeletonHelper;\n\texports.SkinnedMesh = SkinnedMesh;\n\texports.SmoothShading = SmoothShading;\n\texports.Sphere = Sphere;\n\texports.SphereBufferGeometry = SphereBufferGeometry;\n\texports.SphereGeometry = SphereGeometry;\n\texports.Spherical = Spherical;\n\texports.SphericalHarmonics3 = SphericalHarmonics3;\n\texports.SphericalReflectionMapping = SphericalReflectionMapping;\n\texports.Spline = Spline;\n\texports.SplineCurve = SplineCurve;\n\texports.SplineCurve3 = SplineCurve3;\n\texports.SpotLight = SpotLight;\n\texports.SpotLightHelper = SpotLightHelper;\n\texports.SpotLightShadow = SpotLightShadow;\n\texports.Sprite = Sprite;\n\texports.SpriteMaterial = SpriteMaterial;\n\texports.SrcAlphaFactor = SrcAlphaFactor;\n\texports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;\n\texports.SrcColorFactor = SrcColorFactor;\n\texports.StaticCopyUsage = StaticCopyUsage;\n\texports.StaticDrawUsage = StaticDrawUsage;\n\texports.StaticReadUsage = StaticReadUsage;\n\texports.StereoCamera = StereoCamera;\n\texports.StreamCopyUsage = StreamCopyUsage;\n\texports.StreamDrawUsage = StreamDrawUsage;\n\texports.StreamReadUsage = StreamReadUsage;\n\texports.StringKeyframeTrack = StringKeyframeTrack;\n\texports.SubtractEquation = SubtractEquation;\n\texports.SubtractiveBlending = SubtractiveBlending;\n\texports.TOUCH = TOUCH;\n\texports.TangentSpaceNormalMap = TangentSpaceNormalMap;\n\texports.TetrahedronBufferGeometry = TetrahedronBufferGeometry;\n\texports.TetrahedronGeometry = TetrahedronGeometry;\n\texports.TextBufferGeometry = TextBufferGeometry;\n\texports.TextGeometry = TextGeometry;\n\texports.Texture = Texture;\n\texports.TextureLoader = TextureLoader;\n\texports.TorusBufferGeometry = TorusBufferGeometry;\n\texports.TorusGeometry = TorusGeometry;\n\texports.TorusKnotBufferGeometry = TorusKnotBufferGeometry;\n\texports.TorusKnotGeometry = TorusKnotGeometry;\n\texports.Triangle = Triangle;\n\texports.TriangleFanDrawMode = TriangleFanDrawMode;\n\texports.TriangleStripDrawMode = TriangleStripDrawMode;\n\texports.TrianglesDrawMode = TrianglesDrawMode;\n\texports.TubeBufferGeometry = TubeBufferGeometry;\n\texports.TubeGeometry = TubeGeometry;\n\texports.UVMapping = UVMapping;\n\texports.Uint16Attribute = Uint16Attribute;\n\texports.Uint16BufferAttribute = Uint16BufferAttribute;\n\texports.Uint32Attribute = Uint32Attribute;\n\texports.Uint32BufferAttribute = Uint32BufferAttribute;\n\texports.Uint8Attribute = Uint8Attribute;\n\texports.Uint8BufferAttribute = Uint8BufferAttribute;\n\texports.Uint8ClampedAttribute = Uint8ClampedAttribute;\n\texports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;\n\texports.Uncharted2ToneMapping = Uncharted2ToneMapping;\n\texports.Uniform = Uniform;\n\texports.UniformsLib = UniformsLib;\n\texports.UniformsUtils = UniformsUtils;\n\texports.UnsignedByteType = UnsignedByteType;\n\texports.UnsignedInt248Type = UnsignedInt248Type;\n\texports.UnsignedIntType = UnsignedIntType;\n\texports.UnsignedShort4444Type = UnsignedShort4444Type;\n\texports.UnsignedShort5551Type = UnsignedShort5551Type;\n\texports.UnsignedShort565Type = UnsignedShort565Type;\n\texports.UnsignedShortType = UnsignedShortType;\n\texports.VSMShadowMap = VSMShadowMap;\n\texports.Vector2 = Vector2;\n\texports.Vector3 = Vector3;\n\texports.Vector4 = Vector4;\n\texports.VectorKeyframeTrack = VectorKeyframeTrack;\n\texports.Vertex = Vertex;\n\texports.VertexColors = VertexColors;\n\texports.VertexNormalsHelper = VertexNormalsHelper;\n\texports.VertexTangentsHelper = VertexTangentsHelper;\n\texports.VideoTexture = VideoTexture;\n\texports.WebGLMultisampleRenderTarget = WebGLMultisampleRenderTarget;\n\texports.WebGLRenderTarget = WebGLRenderTarget;\n\texports.WebGLRenderTargetCube = WebGLRenderTargetCube;\n\texports.WebGLRenderer = WebGLRenderer;\n\texports.WebGLUtils = WebGLUtils;\n\texports.WireframeGeometry = WireframeGeometry;\n\texports.WireframeHelper = WireframeHelper;\n\texports.WrapAroundEnding = WrapAroundEnding;\n\texports.XHRLoader = XHRLoader;\n\texports.ZeroCurvatureEnding = ZeroCurvatureEnding;\n\texports.ZeroFactor = ZeroFactor;\n\texports.ZeroSlopeEnding = ZeroSlopeEnding;\n\texports.ZeroStencilOp = ZeroStencilOp;\n\texports.sRGBEncoding = sRGBEncoding;\n\n\tObject.defineProperty(exports, '__esModule', { value: true });\n\n})));\n", "/**\r\n * @author Don McCurdy / https://www.donmccurdy.com\r\n */\r\n\r\nTHREE.DRACOLoader = function ( manager ) {\r\n\r\n\tTHREE.Loader.call( this, manager );\r\n\r\n\tthis.decoderPath = '';\r\n\tthis.decoderConfig = {};\r\n\tthis.decoderBinary = null;\r\n\tthis.decoderPending = null;\r\n\r\n\tthis.workerLimit = 4;\r\n\tthis.workerPool = [];\r\n\tthis.workerNextTaskID = 1;\r\n\tthis.workerSourceURL = '';\r\n\r\n\tthis.defaultAttributeIDs = {\r\n\t\tposition: 'POSITION',\r\n\t\tnormal: 'NORMAL',\r\n\t\tcolor: 'COLOR',\r\n\t\tuv: 'TEX_COORD'\r\n\t};\r\n\tthis.defaultAttributeTypes = {\r\n\t\tposition: 'Float32Array',\r\n\t\tnormal: 'Float32Array',\r\n\t\tcolor: 'Float32Array',\r\n\t\tuv: 'Float32Array'\r\n\t};\r\n\r\n};\r\n\r\nTHREE.DRACOLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {\r\n\r\n\tconstructor: THREE.DRACOLoader,\r\n\r\n\tsetDecoderPath: function ( path ) {\r\n\r\n\t\tthis.decoderPath = path;\r\n\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\tsetDecoderConfig: function ( config ) {\r\n\r\n\t\tthis.decoderConfig = config;\r\n\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\tsetWorkerLimit: function ( workerLimit ) {\r\n\r\n\t\tthis.workerLimit = workerLimit;\r\n\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\t/** @deprecated */\r\n\tsetVerbosity: function () {\r\n\r\n\t\tconsole.warn( 'THREE.DRACOLoader: The .setVerbosity() method has been removed.' );\r\n\r\n\t},\r\n\r\n\t/** @deprecated */\r\n\tsetDrawMode: function () {\r\n\r\n\t\tconsole.warn( 'THREE.DRACOLoader: The .setDrawMode() method has been removed.' );\r\n\r\n\t},\r\n\r\n\t/** @deprecated */\r\n\tsetSkipDequantization: function () {\r\n\r\n\t\tconsole.warn( 'THREE.DRACOLoader: The .setSkipDequantization() method has been removed.' );\r\n\r\n\t},\r\n\r\n\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\tvar loader = new THREE.FileLoader( this.manager );\r\n\r\n\t\tloader.setPath( this.path );\r\n\t\tloader.setResponseType( 'arraybuffer' );\r\n\r\n\t\tif ( this.crossOrigin === 'use-credentials' ) {\r\n\r\n\t\t\tloader.setWithCredentials( true );\r\n\r\n\t\t}\r\n\r\n\t\tloader.load( url, ( buffer ) => {\r\n\r\n\t\t\tvar taskConfig = {\r\n\t\t\t\tattributeIDs: this.defaultAttributeIDs,\r\n\t\t\t\tattributeTypes: this.defaultAttributeTypes,\r\n\t\t\t\tuseUniqueIDs: false\r\n\t\t\t};\r\n\r\n\t\t\tthis.decodeGeometry( buffer, taskConfig )\r\n\t\t\t\t.then( onLoad )\r\n\t\t\t\t.catch( onError );\r\n\r\n\t\t}, onProgress, onError );\r\n\r\n\t},\r\n\r\n\t/** @deprecated Kept for backward-compatibility with previous DRACOLoader versions. */\r\n\tdecodeDracoFile: function ( buffer, callback, attributeIDs, attributeTypes ) {\r\n\r\n\t\tvar taskConfig = {\r\n\t\t\tattributeIDs: attributeIDs || this.defaultAttributeIDs,\r\n\t\t\tattributeTypes: attributeTypes || this.defaultAttributeTypes,\r\n\t\t\tuseUniqueIDs: !! attributeIDs\r\n\t\t};\r\n\r\n\t\tthis.decodeGeometry( buffer, taskConfig ).then( callback );\r\n\r\n\t},\r\n\r\n\tdecodeGeometry: function ( buffer, taskConfig ) {\r\n\r\n\t\tvar worker;\r\n\t\tvar taskID = this.workerNextTaskID ++;\r\n\t\tvar taskCost = buffer.byteLength;\r\n\r\n\t\t// TODO: For backward-compatibility, support 'attributeTypes' objects containing\r\n\t\t// references (rather than names) to typed array constructors. These must be\r\n\t\t// serialized before sending them to the worker.\r\n\t\tfor ( var attribute in taskConfig.attributeTypes ) {\r\n\r\n\t\t\tvar type = taskConfig.attributeTypes[ attribute ];\r\n\r\n\t\t\tif ( type.BYTES_PER_ELEMENT !== undefined ) {\r\n\r\n\t\t\t\ttaskConfig.attributeTypes[ attribute ] = type.name;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Obtain a worker and assign a task, and construct a geometry instance\r\n\t\t// when the task completes.\r\n\t\tvar geometryPending = this._getWorker( taskID, taskCost )\r\n\t\t\t.then( ( _worker ) => {\r\n\r\n\t\t\t\tworker = _worker;\r\n\r\n\t\t\t\treturn new Promise( ( resolve, reject ) => {\r\n\r\n\t\t\t\t\tworker._callbacks[ taskID ] = { resolve, reject };\r\n\r\n\t\t\t\t\tworker.postMessage( { type: 'decode', id: taskID, taskConfig, buffer }, [ buffer ] );\r\n\r\n\t\t\t\t\t// this.debug();\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t} )\r\n\t\t\t.then( ( message ) => this._createGeometry( message.geometry ) );\r\n\r\n\t\t// Remove task from the task list.\r\n\t\tgeometryPending\r\n\t\t\t.finally( () => {\r\n\r\n\t\t\t\tif ( worker && taskID ) {\r\n\r\n\t\t\t\t\tthis._releaseTask( worker, taskID );\r\n\r\n\t\t\t\t\t// this.debug();\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} );\r\n\r\n\t\treturn geometryPending;\r\n\r\n\t},\r\n\r\n\t_createGeometry: function ( geometryData ) {\r\n\r\n\t\tvar geometry = new THREE.BufferGeometry();\r\n\r\n\t\tif ( geometryData.index ) {\r\n\r\n\t\t\tgeometry.setIndex( new THREE.BufferAttribute( geometryData.index.array, 1 ) );\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i < geometryData.attributes.length; i ++ ) {\r\n\r\n\t\t\tvar attribute = geometryData.attributes[ i ];\r\n\t\t\tvar name = attribute.name;\r\n\t\t\tvar array = attribute.array;\r\n\t\t\tvar itemSize = attribute.itemSize;\r\n\r\n\t\t\tgeometry.setAttribute( name, new THREE.BufferAttribute( array, itemSize ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn geometry;\r\n\r\n\t},\r\n\r\n\t_loadLibrary: function ( url, responseType ) {\r\n\r\n\t\tvar loader = new THREE.FileLoader( this.manager );\r\n\t\tloader.setPath( this.decoderPath );\r\n\t\tloader.setResponseType( responseType );\r\n\r\n\t\treturn new Promise( ( resolve, reject ) => {\r\n\r\n\t\t\tloader.load( url, resolve, undefined, reject );\r\n\r\n\t\t} );\r\n\r\n\t},\r\n\r\n\tpreload: function () {\r\n\r\n\t\tthis._initDecoder();\r\n\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\t_initDecoder: function () {\r\n\r\n\t\tif ( this.decoderPending ) return this.decoderPending;\r\n\r\n\t\tvar useJS = typeof WebAssembly !== 'object' || this.decoderConfig.type === 'js';\r\n\t\tvar librariesPending = [];\r\n\r\n\t\tif ( useJS ) {\r\n\r\n\t\t\tlibrariesPending.push( this._loadLibrary( 'draco_decoder.js', 'text' ) );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tlibrariesPending.push( this._loadLibrary( 'draco_wasm_wrapper.js', 'text' ) );\r\n\t\t\tlibrariesPending.push( this._loadLibrary( 'draco_decoder.wasm', 'arraybuffer' ) );\r\n\r\n\t\t}\r\n\r\n\t\tthis.decoderPending = Promise.all( librariesPending )\r\n\t\t\t.then( ( libraries ) => {\r\n\r\n\t\t\t\tvar jsContent = libraries[ 0 ];\r\n\r\n\t\t\t\tif ( ! useJS ) {\r\n\r\n\t\t\t\t\tthis.decoderConfig.wasmBinary = libraries[ 1 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar fn = THREE.DRACOLoader.DRACOWorker.toString();\r\n\r\n\t\t\t\tvar body = [\r\n\t\t\t\t\t'/* draco decoder */',\r\n\t\t\t\t\tjsContent,\r\n\t\t\t\t\t'',\r\n\t\t\t\t\t'/* worker */',\r\n\t\t\t\t\tfn.substring( fn.indexOf( '{' ) + 1, fn.lastIndexOf( '}' ) )\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tthis.workerSourceURL = URL.createObjectURL( new Blob( [ body ] ) );\r\n\r\n\t\t\t} );\r\n\r\n\t\treturn this.decoderPending;\r\n\r\n\t},\r\n\r\n\t_getWorker: function ( taskID, taskCost ) {\r\n\r\n\t\treturn this._initDecoder().then( () => {\r\n\r\n\t\t\tif ( this.workerPool.length < this.workerLimit ) {\r\n\r\n\t\t\t\tvar worker = new Worker( this.workerSourceURL );\r\n\r\n\t\t\t\tworker._callbacks = {};\r\n\t\t\t\tworker._taskCosts = {};\r\n\t\t\t\tworker._taskLoad = 0;\r\n\r\n\t\t\t\tworker.postMessage( { type: 'init', decoderConfig: this.decoderConfig } );\r\n\r\n\t\t\t\tworker.onmessage = function ( e ) {\r\n\r\n\t\t\t\t\tvar message = e.data;\r\n\r\n\t\t\t\t\tswitch ( message.type ) {\r\n\r\n\t\t\t\t\t\tcase 'decode':\r\n\t\t\t\t\t\t\tworker._callbacks[ message.id ].resolve( message );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase 'error':\r\n\t\t\t\t\t\t\tworker._callbacks[ message.id ].reject( message );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\t\t\t\t\t\t\tconsole.error( 'THREE.DRACOLoader: Unexpected message, \"' + message.type + '\"' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t};\r\n\r\n\t\t\t\tthis.workerPool.push( worker );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tthis.workerPool.sort( function ( a, b ) {\r\n\r\n\t\t\t\t\treturn a._taskLoad > b._taskLoad ? - 1 : 1;\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar worker = this.workerPool[ this.workerPool.length - 1 ];\r\n\t\t\tworker._taskCosts[ taskID ] = taskCost;\r\n\t\t\tworker._taskLoad += taskCost;\r\n\t\t\treturn worker;\r\n\r\n\t\t} );\r\n\r\n\t},\r\n\r\n\t_releaseTask: function ( worker, taskID ) {\r\n\r\n\t\tworker._taskLoad -= worker._taskCosts[ taskID ];\r\n\t\tdelete worker._callbacks[ taskID ];\r\n\t\tdelete worker._taskCosts[ taskID ];\r\n\r\n\t},\r\n\r\n\tdebug: function () {\r\n\r\n\t\tconsole.log( 'Task load: ', this.workerPool.map( ( worker ) => worker._taskLoad ) );\r\n\r\n\t},\r\n\r\n\tdispose: function () {\r\n\r\n\t\tfor ( var i = 0; i < this.workerPool.length; ++ i ) {\r\n\r\n\t\t\tthis.workerPool[ i ].terminate();\r\n\r\n\t\t}\r\n\r\n\t\tthis.workerPool.length = 0;\r\n\r\n\t\treturn this;\r\n\r\n\t}\r\n\r\n} );\r\n\r\n/* WEB WORKER */\r\n\r\nTHREE.DRACOLoader.DRACOWorker = function () {\r\n\r\n\tvar decoderConfig;\r\n\tvar decoderPending;\r\n\r\n\tonmessage = function ( e ) {\r\n\r\n\t\tvar message = e.data;\r\n\r\n\t\tswitch ( message.type ) {\r\n\r\n\t\t\tcase 'init':\r\n\t\t\t\tdecoderConfig = message.decoderConfig;\r\n\t\t\t\tdecoderPending = new Promise( function ( resolve/*, reject*/ ) {\r\n\r\n\t\t\t\t\tdecoderConfig.onModuleLoaded = function ( draco ) {\r\n\r\n\t\t\t\t\t\t// Module is Promise-like. Wrap before resolving to avoid loop.\r\n\t\t\t\t\t\tresolve( { draco: draco } );\r\n\r\n\t\t\t\t\t};\r\n\r\n\t\t\t\t\tDracoDecoderModule( decoderConfig );\r\n\r\n\t\t\t\t} );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'decode':\r\n\t\t\t\tvar buffer = message.buffer;\r\n\t\t\t\tvar taskConfig = message.taskConfig;\r\n\t\t\t\tdecoderPending.then( ( module ) => {\r\n\r\n\t\t\t\t\tvar draco = module.draco;\r\n\t\t\t\t\tvar decoder = new draco.Decoder();\r\n\t\t\t\t\tvar decoderBuffer = new draco.DecoderBuffer();\r\n\t\t\t\t\tdecoderBuffer.Init( new Int8Array( buffer ), buffer.byteLength );\r\n\r\n\t\t\t\t\ttry {\r\n\r\n\t\t\t\t\t\tvar geometry = decodeGeometry( draco, decoder, decoderBuffer, taskConfig );\r\n\r\n\t\t\t\t\t\tvar buffers = geometry.attributes.map( ( attr ) => attr.array.buffer );\r\n\r\n\t\t\t\t\t\tif ( geometry.index ) buffers.push( geometry.index.array.buffer );\r\n\r\n\t\t\t\t\t\tself.postMessage( { type: 'decode', id: message.id, geometry }, buffers );\r\n\r\n\t\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\t\tconsole.error( error );\r\n\r\n\t\t\t\t\t\tself.postMessage( { type: 'error', id: message.id, error: error.message } );\r\n\r\n\t\t\t\t\t} finally {\r\n\r\n\t\t\t\t\t\tdraco.destroy( decoderBuffer );\r\n\t\t\t\t\t\tdraco.destroy( decoder );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t} );\r\n\t\t\t\tbreak;\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tfunction decodeGeometry( draco, decoder, decoderBuffer, taskConfig ) {\r\n\r\n\t\tvar attributeIDs = taskConfig.attributeIDs;\r\n\t\tvar attributeTypes = taskConfig.attributeTypes;\r\n\r\n\t\tvar dracoGeometry;\r\n\t\tvar decodingStatus;\r\n\r\n\t\tvar geometryType = decoder.GetEncodedGeometryType( decoderBuffer );\r\n\r\n\t\tif ( geometryType === draco.TRIANGULAR_MESH ) {\r\n\r\n\t\t\tdracoGeometry = new draco.Mesh();\r\n\t\t\tdecodingStatus = decoder.DecodeBufferToMesh( decoderBuffer, dracoGeometry );\r\n\r\n\t\t} else if ( geometryType === draco.POINT_CLOUD ) {\r\n\r\n\t\t\tdracoGeometry = new draco.PointCloud();\r\n\t\t\tdecodingStatus = decoder.DecodeBufferToPointCloud( decoderBuffer, dracoGeometry );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tthrow new Error( 'THREE.DRACOLoader: Unexpected geometry type.' );\r\n\r\n\t\t}\r\n\r\n\t\tif ( ! decodingStatus.ok() || dracoGeometry.ptr === 0 ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.DRACOLoader: Decoding failed: ' + decodingStatus.error_msg() );\r\n\r\n\t\t}\r\n\r\n\t\tvar geometry = { index: null, attributes: [] };\r\n\r\n\t\t// Gather all vertex attributes.\r\n\t\tfor ( var attributeName in attributeIDs ) {\r\n\r\n\t\t\tvar attributeType = self[ attributeTypes[ attributeName ] ];\r\n\r\n\t\t\tvar attribute;\r\n\t\t\tvar attributeID;\r\n\r\n\t\t\t// A Draco file may be created with default vertex attributes, whose attribute IDs\r\n\t\t\t// are mapped 1:1 from their semantic name (POSITION, NORMAL, ...). Alternatively,\r\n\t\t\t// a Draco file may contain a custom set of attributes, identified by known unique\r\n\t\t\t// IDs. glTF files always do the latter, and `.drc` files typically do the former.\r\n\t\t\tif ( taskConfig.useUniqueIDs ) {\r\n\r\n\t\t\t\tattributeID = attributeIDs[ attributeName ];\r\n\t\t\t\tattribute = decoder.GetAttributeByUniqueId( dracoGeometry, attributeID );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tattributeID = decoder.GetAttributeId( dracoGeometry, draco[ attributeIDs[ attributeName ] ] );\r\n\r\n\t\t\t\tif ( attributeID === - 1 ) continue;\r\n\r\n\t\t\t\tattribute = decoder.GetAttribute( dracoGeometry, attributeID );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.attributes.push( decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) );\r\n\r\n\t\t}\r\n\r\n\t\t// Add index.\r\n\t\tif ( geometryType === draco.TRIANGULAR_MESH ) {\r\n\r\n\t\t\t// Generate mesh faces.\r\n\t\t\tvar numFaces = dracoGeometry.num_faces();\r\n\t\t\tvar numIndices = numFaces * 3;\r\n\t\t\tvar index = new Uint32Array( numIndices );\r\n\t\t\tvar indexArray = new draco.DracoInt32Array();\r\n\r\n\t\t\tfor ( var i = 0; i < numFaces; ++ i ) {\r\n\r\n\t\t\t\tdecoder.GetFaceFromMesh( dracoGeometry, i, indexArray );\r\n\r\n\t\t\t\tfor ( var j = 0; j < 3; ++ j ) {\r\n\r\n\t\t\t\t\tindex[ i * 3 + j ] = indexArray.GetValue( j );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tgeometry.index = { array: index, itemSize: 1 };\r\n\r\n\t\t\tdraco.destroy( indexArray );\r\n\r\n\t\t}\r\n\r\n\t\tdraco.destroy( dracoGeometry );\r\n\r\n\t\treturn geometry;\r\n\r\n\t}\r\n\r\n\tfunction decodeAttribute( draco, decoder, dracoGeometry, attributeName, attributeType, attribute ) {\r\n\r\n\t\tvar numComponents = attribute.num_components();\r\n\t\tvar numPoints = dracoGeometry.num_points();\r\n\t\tvar numValues = numPoints * numComponents;\r\n\t\tvar dracoArray;\r\n\r\n\t\tvar array;\r\n\r\n\t\tswitch ( attributeType ) {\r\n\r\n\t\t\tcase Float32Array:\r\n\t\t\t\tdracoArray = new draco.DracoFloat32Array();\r\n\t\t\t\tdecoder.GetAttributeFloatForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Float32Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Int8Array:\r\n\t\t\t\tdracoArray = new draco.DracoInt8Array();\r\n\t\t\t\tdecoder.GetAttributeInt8ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Int8Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Int16Array:\r\n\t\t\t\tdracoArray = new draco.DracoInt16Array();\r\n\t\t\t\tdecoder.GetAttributeInt16ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Int16Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Int32Array:\r\n\t\t\t\tdracoArray = new draco.DracoInt32Array();\r\n\t\t\t\tdecoder.GetAttributeInt32ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Int32Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Uint8Array:\r\n\t\t\t\tdracoArray = new draco.DracoUInt8Array();\r\n\t\t\t\tdecoder.GetAttributeUInt8ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Uint8Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Uint16Array:\r\n\t\t\t\tdracoArray = new draco.DracoUInt16Array();\r\n\t\t\t\tdecoder.GetAttributeUInt16ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Uint16Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase Uint32Array:\r\n\t\t\t\tdracoArray = new draco.DracoUInt32Array();\r\n\t\t\t\tdecoder.GetAttributeUInt32ForAllPoints( dracoGeometry, attribute, dracoArray );\r\n\t\t\t\tarray = new Uint32Array( numValues );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'THREE.DRACOLoader: Unexpected attribute type.' );\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var i = 0; i < numValues; i ++ ) {\r\n\r\n\t\t\tarray[ i ] = dracoArray.GetValue( i );\r\n\r\n\t\t}\r\n\r\n\t\tdraco.destroy( dracoArray );\r\n\r\n\t\treturn {\r\n\t\t\tname: attributeName,\r\n\t\t\tarray: array,\r\n\t\t\titemSize: numComponents\r\n\t\t};\r\n\r\n\t}\r\n\r\n};\r\n\r\n/** Deprecated static methods */\r\n\r\n/** @deprecated */\r\nTHREE.DRACOLoader.setDecoderPath = function () {\r\n\r\n\tconsole.warn( 'THREE.DRACOLoader: The .setDecoderPath() method has been removed. Use instance methods.' );\r\n\r\n};\r\n\r\n/** @deprecated */\r\nTHREE.DRACOLoader.setDecoderConfig = function () {\r\n\r\n\tconsole.warn( 'THREE.DRACOLoader: The .setDecoderConfig() method has been removed. Use instance methods.' );\r\n\r\n};\r\n\r\n/** @deprecated */\r\nTHREE.DRACOLoader.releaseDecoderModule = function () {\r\n\r\n\tconsole.warn( 'THREE.DRACOLoader: The .releaseDecoderModule() method has been removed. Use instance methods.' );\r\n\r\n};\r\n\r\n/** @deprecated */\r\nTHREE.DRACOLoader.getDecoderModule = function () {\r\n\r\n\tconsole.warn( 'THREE.DRACOLoader: The .getDecoderModule() method has been removed. Use instance methods.' );\r\n\r\n};\r\n", "/**\r\n * @author Rich Tibbett / https://github.com/richtr\r\n * @author mrdoob / http://mrdoob.com/\r\n * @author Tony Parisi / http://www.tonyparisi.com/\r\n * @author Takahiro / https://github.com/takahirox\r\n * @author Don McCurdy / https://www.donmccurdy.com\r\n */\r\n\r\nTHREE.GLTFLoader = ( function () {\r\n\r\n\tfunction GLTFLoader( manager ) {\r\n\r\n\t\tTHREE.Loader.call( this, manager );\r\n\r\n\t\tthis.dracoLoader = null;\r\n\t\tthis.ddsLoader = null;\r\n\r\n\t}\r\n\r\n\tGLTFLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {\r\n\r\n\t\tconstructor: GLTFLoader,\r\n\r\n\t\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\t\tvar scope = this;\r\n\r\n\t\t\tvar resourcePath;\r\n\r\n\t\t\tif ( this.resourcePath !== '' ) {\r\n\r\n\t\t\t\tresourcePath = this.resourcePath;\r\n\r\n\t\t\t} else if ( this.path !== '' ) {\r\n\r\n\t\t\t\tresourcePath = this.path;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresourcePath = THREE.LoaderUtils.extractUrlBase( url );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Tells the LoadingManager to track an extra item, which resolves after\r\n\t\t\t// the model is fully loaded. This means the count of items loaded will\r\n\t\t\t// be incorrect, but ensures manager.onLoad() does not fire early.\r\n\t\t\tscope.manager.itemStart( url );\r\n\r\n\t\t\tvar _onError = function ( e ) {\r\n\r\n\t\t\t\tif ( onError ) {\r\n\r\n\t\t\t\t\tonError( e );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tconsole.error( e );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tscope.manager.itemError( url );\r\n\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t};\r\n\r\n\t\t\tvar loader = new THREE.FileLoader( scope.manager );\r\n\r\n\t\t\tloader.setPath( this.path );\r\n\t\t\tloader.setResponseType( 'arraybuffer' );\r\n\r\n\t\t\tif ( scope.crossOrigin === 'use-credentials' ) {\r\n\r\n\t\t\t\tloader.setWithCredentials( true );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tloader.load( url, function ( data ) {\r\n\r\n\t\t\t\ttry {\r\n\r\n\t\t\t\t\tscope.parse( data, resourcePath, function ( gltf ) {\r\n\r\n\t\t\t\t\t\tonLoad( gltf );\r\n\r\n\t\t\t\t\t\tscope.manager.itemEnd( url );\r\n\r\n\t\t\t\t\t}, _onError );\r\n\r\n\t\t\t\t} catch ( e ) {\r\n\r\n\t\t\t\t\t_onError( e );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}, onProgress, _onError );\r\n\r\n\t\t},\r\n\r\n\t\tsetDRACOLoader: function ( dracoLoader ) {\r\n\r\n\t\t\tthis.dracoLoader = dracoLoader;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tsetDDSLoader: function ( ddsLoader ) {\r\n\r\n\t\t\tthis.ddsLoader = ddsLoader;\r\n\t\t\treturn this;\r\n\r\n\t\t},\r\n\r\n\t\tparse: function ( data, path, onLoad, onError ) {\r\n\r\n\t\t\tvar content;\r\n\t\t\tvar extensions = {};\r\n\r\n\t\t\tif ( typeof data === 'string' ) {\r\n\r\n\t\t\t\tcontent = data;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar magic = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );\r\n\r\n\t\t\t\tif ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {\r\n\r\n\t\t\t\t\ttry {\r\n\r\n\t\t\t\t\t\textensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );\r\n\r\n\t\t\t\t\t} catch ( error ) {\r\n\r\n\t\t\t\t\t\tif ( onError ) onError( error );\r\n\t\t\t\t\t\treturn;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tcontent = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tcontent = THREE.LoaderUtils.decodeText( new Uint8Array( data ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar json = JSON.parse( content );\r\n\r\n\t\t\tif ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {\r\n\r\n\t\t\t\tif ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );\r\n\t\t\t\treturn;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( json.extensionsUsed ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < json.extensionsUsed.length; ++ i ) {\r\n\r\n\t\t\t\t\tvar extensionName = json.extensionsUsed[ i ];\r\n\t\t\t\t\tvar extensionsRequired = json.extensionsRequired || [];\r\n\r\n\t\t\t\t\tswitch ( extensionName ) {\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_LIGHTS_PUNCTUAL:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFLightsExtension( json );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_UNLIT:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsUnlitExtension();\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.MSFT_TEXTURE_DDS:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFTextureDDSExtension( this.ddsLoader );\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_TEXTURE_TRANSFORM:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFTextureTransformExtension();\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tcase EXTENSIONS.KHR_MESH_QUANTIZATION:\r\n\t\t\t\t\t\t\textensions[ extensionName ] = new GLTFMeshQuantizationExtension();\r\n\t\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\t\tif ( extensionsRequired.indexOf( extensionName ) >= 0 ) {\r\n\r\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Unknown extension \"' + extensionName + '\".' );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar parser = new GLTFParser( json, extensions, {\r\n\r\n\t\t\t\tpath: path || this.resourcePath || '',\r\n\t\t\t\tcrossOrigin: this.crossOrigin,\r\n\t\t\t\tmanager: this.manager\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tparser.parse( onLoad, onError );\r\n\r\n\t\t}\r\n\r\n\t} );\r\n\r\n\t/* GLTFREGISTRY */\r\n\r\n\tfunction GLTFRegistry() {\r\n\r\n\t\tvar objects = {};\r\n\r\n\t\treturn\t{\r\n\r\n\t\t\tget: function ( key ) {\r\n\r\n\t\t\t\treturn objects[ key ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tadd: function ( key, object ) {\r\n\r\n\t\t\t\tobjects[ key ] = object;\r\n\r\n\t\t\t},\r\n\r\n\t\t\tremove: function ( key ) {\r\n\r\n\t\t\t\tdelete objects[ key ];\r\n\r\n\t\t\t},\r\n\r\n\t\t\tremoveAll: function () {\r\n\r\n\t\t\t\tobjects = {};\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t/*********************************/\r\n\t/********** EXTENSIONS ***********/\r\n\t/*********************************/\r\n\r\n\tvar EXTENSIONS = {\r\n\t\tKHR_BINARY_GLTF: 'KHR_binary_glTF',\r\n\t\tKHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',\r\n\t\tKHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',\r\n\t\tKHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',\r\n\t\tKHR_MATERIALS_UNLIT: 'KHR_materials_unlit',\r\n\t\tKHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',\r\n\t\tKHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',\r\n\t\tMSFT_TEXTURE_DDS: 'MSFT_texture_dds'\r\n\t};\r\n\r\n\t/**\r\n\t * DDS Texture Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds\r\n\t *\r\n\t */\r\n\tfunction GLTFTextureDDSExtension( ddsLoader ) {\r\n\r\n\t\tif ( ! ddsLoader ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' );\r\n\r\n\t\t}\r\n\r\n\t\tthis.name = EXTENSIONS.MSFT_TEXTURE_DDS;\r\n\t\tthis.ddsLoader = ddsLoader;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Punctual Lights Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual\r\n\t */\r\n\tfunction GLTFLightsExtension( json ) {\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;\r\n\r\n\t\tvar extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};\r\n\t\tthis.lightDefs = extension.lights || [];\r\n\r\n\t}\r\n\r\n\tGLTFLightsExtension.prototype.loadLight = function ( lightIndex ) {\r\n\r\n\t\tvar lightDef = this.lightDefs[ lightIndex ];\r\n\t\tvar lightNode;\r\n\r\n\t\tvar color = new THREE.Color( 0xffffff );\r\n\t\tif ( lightDef.color !== undefined ) color.fromArray( lightDef.color );\r\n\r\n\t\tvar range = lightDef.range !== undefined ? lightDef.range : 0;\r\n\r\n\t\tswitch ( lightDef.type ) {\r\n\r\n\t\t\tcase 'directional':\r\n\t\t\t\tlightNode = new THREE.DirectionalLight( color );\r\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\r\n\t\t\t\tlightNode.add( lightNode.target );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'point':\r\n\t\t\t\tlightNode = new THREE.PointLight( color );\r\n\t\t\t\tlightNode.distance = range;\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tcase 'spot':\r\n\t\t\t\tlightNode = new THREE.SpotLight( color );\r\n\t\t\t\tlightNode.distance = range;\r\n\t\t\t\t// Handle spotlight properties.\r\n\t\t\t\tlightDef.spot = lightDef.spot || {};\r\n\t\t\t\tlightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;\r\n\t\t\t\tlightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;\r\n\t\t\t\tlightNode.angle = lightDef.spot.outerConeAngle;\r\n\t\t\t\tlightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;\r\n\t\t\t\tlightNode.target.position.set( 0, 0, - 1 );\r\n\t\t\t\tlightNode.add( lightNode.target );\r\n\t\t\t\tbreak;\r\n\r\n\t\t\tdefault:\r\n\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unexpected light type, \"' + lightDef.type + '\".' );\r\n\r\n\t\t}\r\n\r\n\t\t// Some lights (e.g. spot) default to a position other than the origin. Reset the position\r\n\t\t// here, because node-level parsing will only override position if explicitly specified.\r\n\t\tlightNode.position.set( 0, 0, 0 );\r\n\r\n\t\tlightNode.decay = 2;\r\n\r\n\t\tif ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;\r\n\r\n\t\tlightNode.name = lightDef.name || ( 'light_' + lightIndex );\r\n\r\n\t\treturn Promise.resolve( lightNode );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Unlit Materials Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit\r\n\t */\r\n\tfunction GLTFMaterialsUnlitExtension() {\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_MATERIALS_UNLIT;\r\n\r\n\t}\r\n\r\n\tGLTFMaterialsUnlitExtension.prototype.getMaterialType = function () {\r\n\r\n\t\treturn THREE.MeshBasicMaterial;\r\n\r\n\t};\r\n\r\n\tGLTFMaterialsUnlitExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) {\r\n\r\n\t\tvar pending = [];\r\n\r\n\t\tmaterialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );\r\n\t\tmaterialParams.opacity = 1.0;\r\n\r\n\t\tvar metallicRoughness = materialDef.pbrMetallicRoughness;\r\n\r\n\t\tif ( metallicRoughness ) {\r\n\r\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\r\n\r\n\t\t\t\tvar array = metallicRoughness.baseColorFactor;\r\n\r\n\t\t\t\tmaterialParams.color.fromArray( array );\r\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( pending );\r\n\r\n\t};\r\n\r\n\t/* BINARY EXTENSION */\r\n\tvar BINARY_EXTENSION_HEADER_MAGIC = 'glTF';\r\n\tvar BINARY_EXTENSION_HEADER_LENGTH = 12;\r\n\tvar BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };\r\n\r\n\tfunction GLTFBinaryExtension( data ) {\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_BINARY_GLTF;\r\n\t\tthis.content = null;\r\n\t\tthis.body = null;\r\n\r\n\t\tvar headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );\r\n\r\n\t\tthis.header = {\r\n\t\t\tmagic: THREE.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),\r\n\t\t\tversion: headerView.getUint32( 4, true ),\r\n\t\t\tlength: headerView.getUint32( 8, true )\r\n\t\t};\r\n\r\n\t\tif ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );\r\n\r\n\t\t} else if ( this.header.version < 2.0 ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );\r\n\r\n\t\t}\r\n\r\n\t\tvar chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );\r\n\t\tvar chunkIndex = 0;\r\n\r\n\t\twhile ( chunkIndex < chunkView.byteLength ) {\r\n\r\n\t\t\tvar chunkLength = chunkView.getUint32( chunkIndex, true );\r\n\t\t\tchunkIndex += 4;\r\n\r\n\t\t\tvar chunkType = chunkView.getUint32( chunkIndex, true );\r\n\t\t\tchunkIndex += 4;\r\n\r\n\t\t\tif ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {\r\n\r\n\t\t\t\tvar contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );\r\n\t\t\t\tthis.content = THREE.LoaderUtils.decodeText( contentArray );\r\n\r\n\t\t\t} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {\r\n\r\n\t\t\t\tvar byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;\r\n\t\t\t\tthis.body = data.slice( byteOffset, byteOffset + chunkLength );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Clients must ignore chunks with unknown types.\r\n\r\n\t\t\tchunkIndex += chunkLength;\r\n\r\n\t\t}\r\n\r\n\t\tif ( this.content === null ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: JSON content not found.' );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * DRACO Mesh Compression Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression\r\n\t */\r\n\tfunction GLTFDracoMeshCompressionExtension( json, dracoLoader ) {\r\n\r\n\t\tif ( ! dracoLoader ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );\r\n\r\n\t\t}\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;\r\n\t\tthis.json = json;\r\n\t\tthis.dracoLoader = dracoLoader;\r\n\t\tthis.dracoLoader.preload();\r\n\r\n\t}\r\n\r\n\tGLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) {\r\n\r\n\t\tvar json = this.json;\r\n\t\tvar dracoLoader = this.dracoLoader;\r\n\t\tvar bufferViewIndex = primitive.extensions[ this.name ].bufferView;\r\n\t\tvar gltfAttributeMap = primitive.extensions[ this.name ].attributes;\r\n\t\tvar threeAttributeMap = {};\r\n\t\tvar attributeNormalizedMap = {};\r\n\t\tvar attributeTypeMap = {};\r\n\r\n\t\tfor ( var attributeName in gltfAttributeMap ) {\r\n\r\n\t\t\tvar threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\r\n\r\n\t\t\tthreeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];\r\n\r\n\t\t}\r\n\r\n\t\tfor ( attributeName in primitive.attributes ) {\r\n\r\n\t\t\tvar threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();\r\n\r\n\t\t\tif ( gltfAttributeMap[ attributeName ] !== undefined ) {\r\n\r\n\t\t\t\tvar accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];\r\n\t\t\t\tvar componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\r\n\r\n\t\t\t\tattributeTypeMap[ threeAttributeName ] = componentType;\r\n\t\t\t\tattributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {\r\n\r\n\t\t\treturn new Promise( function ( resolve ) {\r\n\r\n\t\t\t\tdracoLoader.decodeDracoFile( bufferView, function ( geometry ) {\r\n\r\n\t\t\t\t\tfor ( var attributeName in geometry.attributes ) {\r\n\r\n\t\t\t\t\t\tvar attribute = geometry.attributes[ attributeName ];\r\n\t\t\t\t\t\tvar normalized = attributeNormalizedMap[ attributeName ];\r\n\r\n\t\t\t\t\t\tif ( normalized !== undefined ) attribute.normalized = normalized;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tresolve( geometry );\r\n\r\n\t\t\t\t}, threeAttributeMap, attributeTypeMap );\r\n\r\n\t\t\t} );\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Texture Transform Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform\r\n\t */\r\n\tfunction GLTFTextureTransformExtension() {\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;\r\n\r\n\t}\r\n\r\n\tGLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) {\r\n\r\n\t\ttexture = texture.clone();\r\n\r\n\t\tif ( transform.offset !== undefined ) {\r\n\r\n\t\t\ttexture.offset.fromArray( transform.offset );\r\n\r\n\t\t}\r\n\r\n\t\tif ( transform.rotation !== undefined ) {\r\n\r\n\t\t\ttexture.rotation = transform.rotation;\r\n\r\n\t\t}\r\n\r\n\t\tif ( transform.scale !== undefined ) {\r\n\r\n\t\t\ttexture.repeat.fromArray( transform.scale );\r\n\r\n\t\t}\r\n\r\n\t\tif ( transform.texCoord !== undefined ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Custom UV sets in \"' + this.name + '\" extension not yet supported.' );\r\n\r\n\t\t}\r\n\r\n\t\ttexture.needsUpdate = true;\r\n\r\n\t\treturn texture;\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specular-Glossiness Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness\r\n\t */\r\n\tfunction GLTFMaterialsPbrSpecularGlossinessExtension() {\r\n\r\n\t\treturn {\r\n\r\n\t\t\tname: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,\r\n\r\n\t\t\tspecularGlossinessParams: [\r\n\t\t\t\t'color',\r\n\t\t\t\t'map',\r\n\t\t\t\t'lightMap',\r\n\t\t\t\t'lightMapIntensity',\r\n\t\t\t\t'aoMap',\r\n\t\t\t\t'aoMapIntensity',\r\n\t\t\t\t'emissive',\r\n\t\t\t\t'emissiveIntensity',\r\n\t\t\t\t'emissiveMap',\r\n\t\t\t\t'bumpMap',\r\n\t\t\t\t'bumpScale',\r\n\t\t\t\t'normalMap',\r\n\t\t\t\t'displacementMap',\r\n\t\t\t\t'displacementScale',\r\n\t\t\t\t'displacementBias',\r\n\t\t\t\t'specularMap',\r\n\t\t\t\t'specular',\r\n\t\t\t\t'glossinessMap',\r\n\t\t\t\t'glossiness',\r\n\t\t\t\t'alphaMap',\r\n\t\t\t\t'envMap',\r\n\t\t\t\t'envMapIntensity',\r\n\t\t\t\t'refractionRatio',\r\n\t\t\t],\r\n\r\n\t\t\tgetMaterialType: function () {\r\n\r\n\t\t\t\treturn THREE.ShaderMaterial;\r\n\r\n\t\t\t},\r\n\r\n\t\t\textendParams: function ( materialParams, materialDef, parser ) {\r\n\r\n\t\t\t\tvar pbrSpecularGlossiness = materialDef.extensions[ this.name ];\r\n\r\n\t\t\t\tvar shader = THREE.ShaderLib[ 'standard' ];\r\n\r\n\t\t\t\tvar uniforms = THREE.UniformsUtils.clone( shader.uniforms );\r\n\r\n\t\t\t\tvar specularMapParsFragmentChunk = [\r\n\t\t\t\t\t'#ifdef USE_SPECULARMAP',\r\n\t\t\t\t\t'\tuniform sampler2D specularMap;',\r\n\t\t\t\t\t'#endif'\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tvar glossinessMapParsFragmentChunk = [\r\n\t\t\t\t\t'#ifdef USE_GLOSSINESSMAP',\r\n\t\t\t\t\t'\tuniform sampler2D glossinessMap;',\r\n\t\t\t\t\t'#endif'\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tvar specularMapFragmentChunk = [\r\n\t\t\t\t\t'vec3 specularFactor = specular;',\r\n\t\t\t\t\t'#ifdef USE_SPECULARMAP',\r\n\t\t\t\t\t'\tvec4 texelSpecular = texture2D( specularMap, vUv );',\r\n\t\t\t\t\t'\ttexelSpecular = sRGBToLinear( texelSpecular );',\r\n\t\t\t\t\t'\t// reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',\r\n\t\t\t\t\t'\tspecularFactor *= texelSpecular.rgb;',\r\n\t\t\t\t\t'#endif'\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tvar glossinessMapFragmentChunk = [\r\n\t\t\t\t\t'float glossinessFactor = glossiness;',\r\n\t\t\t\t\t'#ifdef USE_GLOSSINESSMAP',\r\n\t\t\t\t\t'\tvec4 texelGlossiness = texture2D( glossinessMap, vUv );',\r\n\t\t\t\t\t'\t// reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',\r\n\t\t\t\t\t'\tglossinessFactor *= texelGlossiness.a;',\r\n\t\t\t\t\t'#endif'\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tvar lightPhysicalFragmentChunk = [\r\n\t\t\t\t\t'PhysicalMaterial material;',\r\n\t\t\t\t\t'material.diffuseColor = diffuseColor.rgb;',\r\n\t\t\t\t\t'material.specularRoughness = clamp( 1.0 - glossinessFactor, 0.04, 1.0 );',\r\n\t\t\t\t\t'material.specularColor = specularFactor.rgb;',\r\n\t\t\t\t].join( '\\n' );\r\n\r\n\t\t\t\tvar fragmentShader = shader.fragmentShader\r\n\t\t\t\t\t.replace( 'uniform float roughness;', 'uniform vec3 specular;' )\r\n\t\t\t\t\t.replace( 'uniform float metalness;', 'uniform float glossiness;' )\r\n\t\t\t\t\t.replace( '#include ', specularMapParsFragmentChunk )\r\n\t\t\t\t\t.replace( '#include ', glossinessMapParsFragmentChunk )\r\n\t\t\t\t\t.replace( '#include ', specularMapFragmentChunk )\r\n\t\t\t\t\t.replace( '#include ', glossinessMapFragmentChunk )\r\n\t\t\t\t\t.replace( '#include ', lightPhysicalFragmentChunk );\r\n\r\n\t\t\t\tdelete uniforms.roughness;\r\n\t\t\t\tdelete uniforms.metalness;\r\n\t\t\t\tdelete uniforms.roughnessMap;\r\n\t\t\t\tdelete uniforms.metalnessMap;\r\n\r\n\t\t\t\tuniforms.specular = { value: new THREE.Color().setHex( 0x111111 ) };\r\n\t\t\t\tuniforms.glossiness = { value: 0.5 };\r\n\t\t\t\tuniforms.specularMap = { value: null };\r\n\t\t\t\tuniforms.glossinessMap = { value: null };\r\n\r\n\t\t\t\tmaterialParams.vertexShader = shader.vertexShader;\r\n\t\t\t\tmaterialParams.fragmentShader = fragmentShader;\r\n\t\t\t\tmaterialParams.uniforms = uniforms;\r\n\t\t\t\tmaterialParams.defines = { 'STANDARD': '' };\r\n\r\n\t\t\t\tmaterialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );\r\n\t\t\t\tmaterialParams.opacity = 1.0;\r\n\r\n\t\t\t\tvar pending = [];\r\n\r\n\t\t\t\tif ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {\r\n\r\n\t\t\t\t\tvar array = pbrSpecularGlossiness.diffuseFactor;\r\n\r\n\t\t\t\t\tmaterialParams.color.fromArray( array );\r\n\t\t\t\t\tmaterialParams.opacity = array[ 3 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {\r\n\r\n\t\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmaterialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 );\r\n\t\t\t\tmaterialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;\r\n\t\t\t\tmaterialParams.specular = new THREE.Color( 1.0, 1.0, 1.0 );\r\n\r\n\t\t\t\tif ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {\r\n\r\n\t\t\t\t\tmaterialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {\r\n\r\n\t\t\t\t\tvar specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;\r\n\t\t\t\t\tpending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );\r\n\t\t\t\t\tpending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn Promise.all( pending );\r\n\r\n\t\t\t},\r\n\r\n\t\t\tcreateMaterial: function ( params ) {\r\n\r\n\t\t\t\t// setup material properties based on MeshStandardMaterial for Specular-Glossiness\r\n\r\n\t\t\t\tvar material = new THREE.ShaderMaterial( {\r\n\t\t\t\t\tdefines: params.defines,\r\n\t\t\t\t\tvertexShader: params.vertexShader,\r\n\t\t\t\t\tfragmentShader: params.fragmentShader,\r\n\t\t\t\t\tuniforms: params.uniforms,\r\n\t\t\t\t\tfog: true,\r\n\t\t\t\t\tlights: true,\r\n\t\t\t\t\topacity: params.opacity,\r\n\t\t\t\t\ttransparent: params.transparent\r\n\t\t\t\t} );\r\n\r\n\t\t\t\tmaterial.isGLTFSpecularGlossinessMaterial = true;\r\n\r\n\t\t\t\tmaterial.color = params.color;\r\n\r\n\t\t\t\tmaterial.map = params.map === undefined ? null : params.map;\r\n\r\n\t\t\t\tmaterial.lightMap = null;\r\n\t\t\t\tmaterial.lightMapIntensity = 1.0;\r\n\r\n\t\t\t\tmaterial.aoMap = params.aoMap === undefined ? null : params.aoMap;\r\n\t\t\t\tmaterial.aoMapIntensity = 1.0;\r\n\r\n\t\t\t\tmaterial.emissive = params.emissive;\r\n\t\t\t\tmaterial.emissiveIntensity = 1.0;\r\n\t\t\t\tmaterial.emissiveMap = params.emissiveMap === undefined ? null : params.emissiveMap;\r\n\r\n\t\t\t\tmaterial.bumpMap = params.bumpMap === undefined ? null : params.bumpMap;\r\n\t\t\t\tmaterial.bumpScale = 1;\r\n\r\n\t\t\t\tmaterial.normalMap = params.normalMap === undefined ? null : params.normalMap;\r\n\r\n\t\t\t\tif ( params.normalScale ) material.normalScale = params.normalScale;\r\n\r\n\t\t\t\tmaterial.displacementMap = null;\r\n\t\t\t\tmaterial.displacementScale = 1;\r\n\t\t\t\tmaterial.displacementBias = 0;\r\n\r\n\t\t\t\tmaterial.specularMap = params.specularMap === undefined ? null : params.specularMap;\r\n\t\t\t\tmaterial.specular = params.specular;\r\n\r\n\t\t\t\tmaterial.glossinessMap = params.glossinessMap === undefined ? null : params.glossinessMap;\r\n\t\t\t\tmaterial.glossiness = params.glossiness;\r\n\r\n\t\t\t\tmaterial.alphaMap = null;\r\n\r\n\t\t\t\tmaterial.envMap = params.envMap === undefined ? null : params.envMap;\r\n\t\t\t\tmaterial.envMapIntensity = 1.0;\r\n\r\n\t\t\t\tmaterial.refractionRatio = 0.98;\r\n\r\n\t\t\t\tmaterial.extensions.derivatives = true;\r\n\r\n\t\t\t\treturn material;\r\n\r\n\t\t\t},\r\n\r\n\t\t\t/**\r\n\t\t\t * Clones a GLTFSpecularGlossinessMaterial instance. The ShaderMaterial.copy() method can\r\n\t\t\t * copy only properties it knows about or inherits, and misses many properties that would\r\n\t\t\t * normally be defined by MeshStandardMaterial.\r\n\t\t\t *\r\n\t\t\t * This method allows GLTFSpecularGlossinessMaterials to be cloned in the process of\r\n\t\t\t * loading a glTF model, but cloning later (e.g. by the user) would require these changes\r\n\t\t\t * AND also updating `.onBeforeRender` on the parent mesh.\r\n\t\t\t *\r\n\t\t\t * @param {THREE.ShaderMaterial} source\r\n\t\t\t * @return {THREE.ShaderMaterial}\r\n\t\t\t */\r\n\t\t\tcloneMaterial: function ( source ) {\r\n\r\n\t\t\t\tvar target = source.clone();\r\n\r\n\t\t\t\ttarget.isGLTFSpecularGlossinessMaterial = true;\r\n\r\n\t\t\t\tvar params = this.specularGlossinessParams;\r\n\r\n\t\t\t\tfor ( var i = 0, il = params.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar value = source[ params[ i ] ];\r\n\t\t\t\t\ttarget[ params[ i ] ] = ( value && value.isColor ) ? value.clone() : value;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn target;\r\n\r\n\t\t\t},\r\n\r\n\t\t\t// Here's based on refreshUniformsCommon() and refreshUniformsStandard() in WebGLRenderer.\r\n\t\t\trefreshUniforms: function ( renderer, scene, camera, geometry, material ) {\r\n\r\n\t\t\t\tif ( material.isGLTFSpecularGlossinessMaterial !== true ) {\r\n\r\n\t\t\t\t\treturn;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar uniforms = material.uniforms;\r\n\t\t\t\tvar defines = material.defines;\r\n\r\n\t\t\t\tuniforms.opacity.value = material.opacity;\r\n\r\n\t\t\t\tuniforms.diffuse.value.copy( material.color );\r\n\t\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\r\n\r\n\t\t\t\tuniforms.map.value = material.map;\r\n\t\t\t\tuniforms.specularMap.value = material.specularMap;\r\n\t\t\t\tuniforms.alphaMap.value = material.alphaMap;\r\n\r\n\t\t\t\tuniforms.lightMap.value = material.lightMap;\r\n\t\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\r\n\r\n\t\t\t\tuniforms.aoMap.value = material.aoMap;\r\n\t\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\r\n\r\n\t\t\t\t// uv repeat and offset setting priorities\r\n\t\t\t\t// 1. color map\r\n\t\t\t\t// 2. specular map\r\n\t\t\t\t// 3. normal map\r\n\t\t\t\t// 4. bump map\r\n\t\t\t\t// 5. alpha map\r\n\t\t\t\t// 6. emissive map\r\n\r\n\t\t\t\tvar uvScaleMap;\r\n\r\n\t\t\t\tif ( material.map ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.map;\r\n\r\n\t\t\t\t} else if ( material.specularMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.specularMap;\r\n\r\n\t\t\t\t} else if ( material.displacementMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.displacementMap;\r\n\r\n\t\t\t\t} else if ( material.normalMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.normalMap;\r\n\r\n\t\t\t\t} else if ( material.bumpMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.bumpMap;\r\n\r\n\t\t\t\t} else if ( material.glossinessMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.glossinessMap;\r\n\r\n\t\t\t\t} else if ( material.alphaMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.alphaMap;\r\n\r\n\t\t\t\t} else if ( material.emissiveMap ) {\r\n\r\n\t\t\t\t\tuvScaleMap = material.emissiveMap;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uvScaleMap !== undefined ) {\r\n\r\n\t\t\t\t\t// backwards compatibility\r\n\t\t\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\r\n\r\n\t\t\t\t\t\tuvScaleMap = uvScaleMap.texture;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\r\n\r\n\t\t\t\t\t\tuvScaleMap.updateMatrix();\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( material.envMap ) {\r\n\r\n\t\t\t\t\tuniforms.envMap.value = material.envMap;\r\n\t\t\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\r\n\r\n\t\t\t\t\t// don't flip CubeTexture envMaps, flip everything else:\r\n\t\t\t\t\t// WebGLRenderTargetCube will be flipped for backwards compatibility\r\n\t\t\t\t\t// WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture\r\n\t\t\t\t\t// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future\r\n\t\t\t\t\tuniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;\r\n\r\n\t\t\t\t\tuniforms.reflectivity.value = material.reflectivity;\r\n\t\t\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\r\n\r\n\t\t\t\t\tuniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tuniforms.specular.value.copy( material.specular );\r\n\t\t\t\tuniforms.glossiness.value = material.glossiness;\r\n\r\n\t\t\t\tuniforms.glossinessMap.value = material.glossinessMap;\r\n\r\n\t\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\r\n\t\t\t\tuniforms.bumpMap.value = material.bumpMap;\r\n\t\t\t\tuniforms.normalMap.value = material.normalMap;\r\n\r\n\t\t\t\tuniforms.displacementMap.value = material.displacementMap;\r\n\t\t\t\tuniforms.displacementScale.value = material.displacementScale;\r\n\t\t\t\tuniforms.displacementBias.value = material.displacementBias;\r\n\r\n\t\t\t\tif ( uniforms.glossinessMap.value !== null && defines.USE_GLOSSINESSMAP === undefined ) {\r\n\r\n\t\t\t\t\tdefines.USE_GLOSSINESSMAP = '';\r\n\t\t\t\t\t// set USE_ROUGHNESSMAP to enable vUv\r\n\t\t\t\t\tdefines.USE_ROUGHNESSMAP = '';\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( uniforms.glossinessMap.value === null && defines.USE_GLOSSINESSMAP !== undefined ) {\r\n\r\n\t\t\t\t\tdelete defines.USE_GLOSSINESSMAP;\r\n\t\t\t\t\tdelete defines.USE_ROUGHNESSMAP;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t};\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Mesh Quantization Extension\r\n\t *\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization\r\n\t */\r\n\tfunction GLTFMeshQuantizationExtension() {\r\n\r\n\t\tthis.name = EXTENSIONS.KHR_MESH_QUANTIZATION;\r\n\r\n\t}\r\n\r\n\t/*********************************/\r\n\t/********** INTERPOLATION ********/\r\n\t/*********************************/\r\n\r\n\t// Spline Interpolation\r\n\t// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation\r\n\tfunction GLTFCubicSplineInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {\r\n\r\n\t\tTHREE.Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );\r\n\r\n\t}\r\n\r\n\tGLTFCubicSplineInterpolant.prototype = Object.create( THREE.Interpolant.prototype );\r\n\tGLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;\r\n\r\n\tGLTFCubicSplineInterpolant.prototype.copySampleValue_ = function ( index ) {\r\n\r\n\t\t// Copies a sample value to the result buffer. See description of glTF\r\n\t\t// CUBICSPLINE values layout in interpolate_() function below.\r\n\r\n\t\tvar result = this.resultBuffer,\r\n\t\t\tvalues = this.sampleValues,\r\n\t\t\tvalueSize = this.valueSize,\r\n\t\t\toffset = index * valueSize * 3 + valueSize;\r\n\r\n\t\tfor ( var i = 0; i !== valueSize; i ++ ) {\r\n\r\n\t\t\tresult[ i ] = values[ offset + i ];\r\n\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\r\n\t};\r\n\r\n\tGLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\r\n\r\n\tGLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;\r\n\r\n\tGLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {\r\n\r\n\t\tvar result = this.resultBuffer;\r\n\t\tvar values = this.sampleValues;\r\n\t\tvar stride = this.valueSize;\r\n\r\n\t\tvar stride2 = stride * 2;\r\n\t\tvar stride3 = stride * 3;\r\n\r\n\t\tvar td = t1 - t0;\r\n\r\n\t\tvar p = ( t - t0 ) / td;\r\n\t\tvar pp = p * p;\r\n\t\tvar ppp = pp * p;\r\n\r\n\t\tvar offset1 = i1 * stride3;\r\n\t\tvar offset0 = offset1 - stride3;\r\n\r\n\t\tvar s2 = - 2 * ppp + 3 * pp;\r\n\t\tvar s3 = ppp - pp;\r\n\t\tvar s0 = 1 - s2;\r\n\t\tvar s1 = s3 - pp + p;\r\n\r\n\t\t// Layout of keyframe output values for CUBICSPLINE animations:\r\n\t\t// [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]\r\n\t\tfor ( var i = 0; i !== stride; i ++ ) {\r\n\r\n\t\t\tvar p0 = values[ offset0 + i + stride ]; // splineVertex_k\r\n\t\t\tvar m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)\r\n\t\t\tvar p1 = values[ offset1 + i + stride ]; // splineVertex_k+1\r\n\t\t\tvar m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)\r\n\r\n\t\t\tresult[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;\r\n\r\n\t\t}\r\n\r\n\t\treturn result;\r\n\r\n\t};\r\n\r\n\t/*********************************/\r\n\t/********** INTERNALS ************/\r\n\t/*********************************/\r\n\r\n\t/* CONSTANTS */\r\n\r\n\tvar WEBGL_CONSTANTS = {\r\n\t\tFLOAT: 5126,\r\n\t\t//FLOAT_MAT2: 35674,\r\n\t\tFLOAT_MAT3: 35675,\r\n\t\tFLOAT_MAT4: 35676,\r\n\t\tFLOAT_VEC2: 35664,\r\n\t\tFLOAT_VEC3: 35665,\r\n\t\tFLOAT_VEC4: 35666,\r\n\t\tLINEAR: 9729,\r\n\t\tREPEAT: 10497,\r\n\t\tSAMPLER_2D: 35678,\r\n\t\tPOINTS: 0,\r\n\t\tLINES: 1,\r\n\t\tLINE_LOOP: 2,\r\n\t\tLINE_STRIP: 3,\r\n\t\tTRIANGLES: 4,\r\n\t\tTRIANGLE_STRIP: 5,\r\n\t\tTRIANGLE_FAN: 6,\r\n\t\tUNSIGNED_BYTE: 5121,\r\n\t\tUNSIGNED_SHORT: 5123\r\n\t};\r\n\r\n\tvar WEBGL_COMPONENT_TYPES = {\r\n\t\t5120: Int8Array,\r\n\t\t5121: Uint8Array,\r\n\t\t5122: Int16Array,\r\n\t\t5123: Uint16Array,\r\n\t\t5125: Uint32Array,\r\n\t\t5126: Float32Array\r\n\t};\r\n\r\n\tvar WEBGL_FILTERS = {\r\n\t\t9728: THREE.NearestFilter,\r\n\t\t9729: THREE.LinearFilter,\r\n\t\t9984: THREE.NearestMipmapNearestFilter,\r\n\t\t9985: THREE.LinearMipmapNearestFilter,\r\n\t\t9986: THREE.NearestMipmapLinearFilter,\r\n\t\t9987: THREE.LinearMipmapLinearFilter\r\n\t};\r\n\r\n\tvar WEBGL_WRAPPINGS = {\r\n\t\t33071: THREE.ClampToEdgeWrapping,\r\n\t\t33648: THREE.MirroredRepeatWrapping,\r\n\t\t10497: THREE.RepeatWrapping\r\n\t};\r\n\r\n\tvar WEBGL_TYPE_SIZES = {\r\n\t\t'SCALAR': 1,\r\n\t\t'VEC2': 2,\r\n\t\t'VEC3': 3,\r\n\t\t'VEC4': 4,\r\n\t\t'MAT2': 4,\r\n\t\t'MAT3': 9,\r\n\t\t'MAT4': 16\r\n\t};\r\n\r\n\tvar ATTRIBUTES = {\r\n\t\tPOSITION: 'position',\r\n\t\tNORMAL: 'normal',\r\n\t\tTANGENT: 'tangent',\r\n\t\tTEXCOORD_0: 'uv',\r\n\t\tTEXCOORD_1: 'uv2',\r\n\t\tCOLOR_0: 'color',\r\n\t\tWEIGHTS_0: 'skinWeight',\r\n\t\tJOINTS_0: 'skinIndex',\r\n\t};\r\n\r\n\tvar PATH_PROPERTIES = {\r\n\t\tscale: 'scale',\r\n\t\ttranslation: 'position',\r\n\t\trotation: 'quaternion',\r\n\t\tweights: 'morphTargetInfluences'\r\n\t};\r\n\r\n\tvar INTERPOLATION = {\r\n\t\tCUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each\r\n\t\t // keyframe track will be initialized with a default interpolation type, then modified.\r\n\t\tLINEAR: THREE.InterpolateLinear,\r\n\t\tSTEP: THREE.InterpolateDiscrete\r\n\t};\r\n\r\n\tvar ALPHA_MODES = {\r\n\t\tOPAQUE: 'OPAQUE',\r\n\t\tMASK: 'MASK',\r\n\t\tBLEND: 'BLEND'\r\n\t};\r\n\r\n\tvar MIME_TYPE_FORMATS = {\r\n\t\t'image/png': THREE.RGBAFormat,\r\n\t\t'image/jpeg': THREE.RGBFormat\r\n\t};\r\n\r\n\t/* UTILITY FUNCTIONS */\r\n\r\n\tfunction resolveURL( url, path ) {\r\n\r\n\t\t// Invalid URL\r\n\t\tif ( typeof url !== 'string' || url === '' ) return '';\r\n\r\n\t\t// Host Relative URL\r\n\t\tif ( /^https?:\\/\\//i.test( path ) && /^\\//.test( url ) ) {\r\n\r\n\t\t\tpath = path.replace( /(^https?:\\/\\/[^\\/]+).*/i, '$1' );\r\n\r\n\t\t}\r\n\r\n\t\t// Absolute URL http://,https://,//\r\n\t\tif ( /^(https?:)?\\/\\//i.test( url ) ) return url;\r\n\r\n\t\t// Data URI\r\n\t\tif ( /^data:.*,.*$/i.test( url ) ) return url;\r\n\r\n\t\t// Blob URL\r\n\t\tif ( /^blob:.*$/i.test( url ) ) return url;\r\n\r\n\t\t// Relative URL\r\n\t\treturn path + url;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material\r\n\t */\r\n\tfunction createDefaultMaterial( cache ) {\r\n\r\n\t\tif ( cache[ 'DefaultMaterial' ] === undefined ) {\r\n\r\n\t\t\tcache[ 'DefaultMaterial' ] = new THREE.MeshStandardMaterial( {\r\n\t\t\t\tcolor: 0xFFFFFF,\r\n\t\t\t\temissive: 0x000000,\r\n\t\t\t\tmetalness: 1,\r\n\t\t\t\troughness: 1,\r\n\t\t\t\ttransparent: false,\r\n\t\t\t\tdepthTest: true,\r\n\t\t\t\tside: THREE.FrontSide\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\treturn cache[ 'DefaultMaterial' ];\r\n\r\n\t}\r\n\r\n\tfunction addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {\r\n\r\n\t\t// Add unknown glTF extensions to an object's userData.\r\n\r\n\t\tfor ( var name in objectDef.extensions ) {\r\n\r\n\t\t\tif ( knownExtensions[ name ] === undefined ) {\r\n\r\n\t\t\t\tobject.userData.gltfExtensions = object.userData.gltfExtensions || {};\r\n\t\t\t\tobject.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object\r\n\t * @param {GLTF.definition} gltfDef\r\n\t */\r\n\tfunction assignExtrasToUserData( object, gltfDef ) {\r\n\r\n\t\tif ( gltfDef.extras !== undefined ) {\r\n\r\n\t\t\tif ( typeof gltfDef.extras === 'object' ) {\r\n\r\n\t\t\t\tObject.assign( object.userData, gltfDef.extras );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets\r\n\t *\r\n\t * @param {THREE.BufferGeometry} geometry\r\n\t * @param {Array} targets\r\n\t * @param {GLTFParser} parser\r\n\t * @return {Promise}\r\n\t */\r\n\tfunction addMorphTargets( geometry, targets, parser ) {\r\n\r\n\t\tvar hasMorphPosition = false;\r\n\t\tvar hasMorphNormal = false;\r\n\r\n\t\tfor ( var i = 0, il = targets.length; i < il; i ++ ) {\r\n\r\n\t\t\tvar target = targets[ i ];\r\n\r\n\t\t\tif ( target.POSITION !== undefined ) hasMorphPosition = true;\r\n\t\t\tif ( target.NORMAL !== undefined ) hasMorphNormal = true;\r\n\r\n\t\t\tif ( hasMorphPosition && hasMorphNormal ) break;\r\n\r\n\t\t}\r\n\r\n\t\tif ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry );\r\n\r\n\t\tvar pendingPositionAccessors = [];\r\n\t\tvar pendingNormalAccessors = [];\r\n\r\n\t\tfor ( var i = 0, il = targets.length; i < il; i ++ ) {\r\n\r\n\t\t\tvar target = targets[ i ];\r\n\r\n\t\t\tif ( hasMorphPosition ) {\r\n\r\n\t\t\t\tvar pendingAccessor = target.POSITION !== undefined\r\n\t\t\t\t\t? parser.getDependency( 'accessor', target.POSITION )\r\n\t\t\t\t\t: geometry.attributes.position;\r\n\r\n\t\t\t\tpendingPositionAccessors.push( pendingAccessor );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( hasMorphNormal ) {\r\n\r\n\t\t\t\tvar pendingAccessor = target.NORMAL !== undefined\r\n\t\t\t\t\t? parser.getDependency( 'accessor', target.NORMAL )\r\n\t\t\t\t\t: geometry.attributes.normal;\r\n\r\n\t\t\t\tpendingNormalAccessors.push( pendingAccessor );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( [\r\n\t\t\tPromise.all( pendingPositionAccessors ),\r\n\t\t\tPromise.all( pendingNormalAccessors )\r\n\t\t] ).then( function ( accessors ) {\r\n\r\n\t\t\tvar morphPositions = accessors[ 0 ];\r\n\t\t\tvar morphNormals = accessors[ 1 ];\r\n\r\n\t\t\tif ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;\r\n\t\t\tif ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;\r\n\t\t\tgeometry.morphTargetsRelative = true;\r\n\r\n\t\t\treturn geometry;\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * @param {THREE.Mesh} mesh\r\n\t * @param {GLTF.Mesh} meshDef\r\n\t */\r\n\tfunction updateMorphTargets( mesh, meshDef ) {\r\n\r\n\t\tmesh.updateMorphTargets();\r\n\r\n\t\tif ( meshDef.weights !== undefined ) {\r\n\r\n\t\t\tfor ( var i = 0, il = meshDef.weights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tmesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// .extras has user-defined data, so check that .extras.targetNames is an array.\r\n\t\tif ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {\r\n\r\n\t\t\tvar targetNames = meshDef.extras.targetNames;\r\n\r\n\t\t\tif ( mesh.morphTargetInfluences.length === targetNames.length ) {\r\n\r\n\t\t\t\tmesh.morphTargetDictionary = {};\r\n\r\n\t\t\t\tfor ( var i = 0, il = targetNames.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tmesh.morphTargetDictionary[ targetNames[ i ] ] = i;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tfunction createPrimitiveKey( primitiveDef ) {\r\n\r\n\t\tvar dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];\r\n\t\tvar geometryKey;\r\n\r\n\t\tif ( dracoExtension ) {\r\n\r\n\t\t\tgeometryKey = 'draco:' + dracoExtension.bufferView\r\n\t\t\t\t+ ':' + dracoExtension.indices\r\n\t\t\t\t+ ':' + createAttributesKey( dracoExtension.attributes );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tgeometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;\r\n\r\n\t\t}\r\n\r\n\t\treturn geometryKey;\r\n\r\n\t}\r\n\r\n\tfunction createAttributesKey( attributes ) {\r\n\r\n\t\tvar attributesKey = '';\r\n\r\n\t\tvar keys = Object.keys( attributes ).sort();\r\n\r\n\t\tfor ( var i = 0, il = keys.length; i < il; i ++ ) {\r\n\r\n\t\t\tattributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';\r\n\r\n\t\t}\r\n\r\n\t\treturn attributesKey;\r\n\r\n\t}\r\n\r\n\t/* GLTF PARSER */\r\n\r\n\tfunction GLTFParser( json, extensions, options ) {\r\n\r\n\t\tthis.json = json || {};\r\n\t\tthis.extensions = extensions || {};\r\n\t\tthis.options = options || {};\r\n\r\n\t\t// loader object cache\r\n\t\tthis.cache = new GLTFRegistry();\r\n\r\n\t\t// BufferGeometry caching\r\n\t\tthis.primitiveCache = {};\r\n\r\n\t\tthis.textureLoader = new THREE.TextureLoader( this.options.manager );\r\n\t\tthis.textureLoader.setCrossOrigin( this.options.crossOrigin );\r\n\r\n\t\tthis.fileLoader = new THREE.FileLoader( this.options.manager );\r\n\t\tthis.fileLoader.setResponseType( 'arraybuffer' );\r\n\r\n\t\tif ( this.options.crossOrigin === 'use-credentials' ) {\r\n\r\n\t\t\tthis.fileLoader.setWithCredentials( true );\r\n\r\n\t\t}\r\n\r\n\t}\r\n\r\n\tGLTFParser.prototype.parse = function ( onLoad, onError ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar json = this.json;\r\n\t\tvar extensions = this.extensions;\r\n\r\n\t\t// Clear the loader cache\r\n\t\tthis.cache.removeAll();\r\n\r\n\t\t// Mark the special nodes/meshes in json for efficient parse\r\n\t\tthis.markDefs();\r\n\r\n\t\tPromise.all( [\r\n\r\n\t\t\tthis.getDependencies( 'scene' ),\r\n\t\t\tthis.getDependencies( 'animation' ),\r\n\t\t\tthis.getDependencies( 'camera' ),\r\n\r\n\t\t] ).then( function ( dependencies ) {\r\n\r\n\t\t\tvar result = {\r\n\t\t\t\tscene: dependencies[ 0 ][ json.scene || 0 ],\r\n\t\t\t\tscenes: dependencies[ 0 ],\r\n\t\t\t\tanimations: dependencies[ 1 ],\r\n\t\t\t\tcameras: dependencies[ 2 ],\r\n\t\t\t\tasset: json.asset,\r\n\t\t\t\tparser: parser,\r\n\t\t\t\tuserData: {}\r\n\t\t\t};\r\n\r\n\t\t\taddUnknownExtensionsToUserData( extensions, result, json );\r\n\r\n\t\t\tassignExtrasToUserData( result, json );\r\n\r\n\t\t\tonLoad( result );\r\n\r\n\t\t} ).catch( onError );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Marks the special nodes/meshes in json for efficient parse.\r\n\t */\r\n\tGLTFParser.prototype.markDefs = function () {\r\n\r\n\t\tvar nodeDefs = this.json.nodes || [];\r\n\t\tvar skinDefs = this.json.skins || [];\r\n\t\tvar meshDefs = this.json.meshes || [];\r\n\r\n\t\tvar meshReferences = {};\r\n\t\tvar meshUses = {};\r\n\r\n\t\t// Nothing in the node definition indicates whether it is a Bone or an\r\n\t\t// Object3D. Use the skins' joint references to mark bones.\r\n\t\tfor ( var skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {\r\n\r\n\t\t\tvar joints = skinDefs[ skinIndex ].joints;\r\n\r\n\t\t\tfor ( var i = 0, il = joints.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tnodeDefs[ joints[ i ] ].isBone = true;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t// Meshes can (and should) be reused by multiple nodes in a glTF asset. To\r\n\t\t// avoid having more than one THREE.Mesh with the same name, count\r\n\t\t// references and rename instances below.\r\n\t\t//\r\n\t\t// Example: CesiumMilkTruck sample model reuses \"Wheel\" meshes.\r\n\t\tfor ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {\r\n\r\n\t\t\tvar nodeDef = nodeDefs[ nodeIndex ];\r\n\r\n\t\t\tif ( nodeDef.mesh !== undefined ) {\r\n\r\n\t\t\t\tif ( meshReferences[ nodeDef.mesh ] === undefined ) {\r\n\r\n\t\t\t\t\tmeshReferences[ nodeDef.mesh ] = meshUses[ nodeDef.mesh ] = 0;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tmeshReferences[ nodeDef.mesh ] ++;\r\n\r\n\t\t\t\t// Nothing in the mesh definition indicates whether it is\r\n\t\t\t\t// a SkinnedMesh or Mesh. Use the node's mesh reference\r\n\t\t\t\t// to mark SkinnedMesh if node has skin.\r\n\t\t\t\tif ( nodeDef.skin !== undefined ) {\r\n\r\n\t\t\t\t\tmeshDefs[ nodeDef.mesh ].isSkinnedMesh = true;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.json.meshReferences = meshReferences;\r\n\t\tthis.json.meshUses = meshUses;\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Requests the specified dependency asynchronously, with caching.\r\n\t * @param {string} type\r\n\t * @param {number} index\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.getDependency = function ( type, index ) {\r\n\r\n\t\tvar cacheKey = type + ':' + index;\r\n\t\tvar dependency = this.cache.get( cacheKey );\r\n\r\n\t\tif ( ! dependency ) {\r\n\r\n\t\t\tswitch ( type ) {\r\n\r\n\t\t\t\tcase 'scene':\r\n\t\t\t\t\tdependency = this.loadScene( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'node':\r\n\t\t\t\t\tdependency = this.loadNode( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'mesh':\r\n\t\t\t\t\tdependency = this.loadMesh( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'accessor':\r\n\t\t\t\t\tdependency = this.loadAccessor( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'bufferView':\r\n\t\t\t\t\tdependency = this.loadBufferView( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'buffer':\r\n\t\t\t\t\tdependency = this.loadBuffer( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'material':\r\n\t\t\t\t\tdependency = this.loadMaterial( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'texture':\r\n\t\t\t\t\tdependency = this.loadTexture( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'skin':\r\n\t\t\t\t\tdependency = this.loadSkin( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'animation':\r\n\t\t\t\t\tdependency = this.loadAnimation( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'camera':\r\n\t\t\t\t\tdependency = this.loadCamera( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'light':\r\n\t\t\t\t\tdependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tthrow new Error( 'Unknown type: ' + type );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tthis.cache.add( cacheKey, dependency );\r\n\r\n\t\t}\r\n\r\n\t\treturn dependency;\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Requests all dependencies of the specified type asynchronously, with caching.\r\n\t * @param {string} type\r\n\t * @return {Promise>}\r\n\t */\r\n\tGLTFParser.prototype.getDependencies = function ( type ) {\r\n\r\n\t\tvar dependencies = this.cache.get( type );\r\n\r\n\t\tif ( ! dependencies ) {\r\n\r\n\t\t\tvar parser = this;\r\n\t\t\tvar defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];\r\n\r\n\t\t\tdependencies = Promise.all( defs.map( function ( def, index ) {\r\n\r\n\t\t\t\treturn parser.getDependency( type, index );\r\n\r\n\t\t\t} ) );\r\n\r\n\t\t\tthis.cache.add( type, dependencies );\r\n\r\n\t\t}\r\n\r\n\t\treturn dependencies;\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\r\n\t * @param {number} bufferIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadBuffer = function ( bufferIndex ) {\r\n\r\n\t\tvar bufferDef = this.json.buffers[ bufferIndex ];\r\n\t\tvar loader = this.fileLoader;\r\n\r\n\t\tif ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {\r\n\r\n\t\t\tthrow new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );\r\n\r\n\t\t}\r\n\r\n\t\t// If present, GLB container is required to be the first buffer.\r\n\t\tif ( bufferDef.uri === undefined && bufferIndex === 0 ) {\r\n\r\n\t\t\treturn Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );\r\n\r\n\t\t}\r\n\r\n\t\tvar options = this.options;\r\n\r\n\t\treturn new Promise( function ( resolve, reject ) {\r\n\r\n\t\t\tloader.load( resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {\r\n\r\n\t\t\t\treject( new Error( 'THREE.GLTFLoader: Failed to load buffer \"' + bufferDef.uri + '\".' ) );\r\n\r\n\t\t\t} );\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views\r\n\t * @param {number} bufferViewIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadBufferView = function ( bufferViewIndex ) {\r\n\r\n\t\tvar bufferViewDef = this.json.bufferViews[ bufferViewIndex ];\r\n\r\n\t\treturn this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {\r\n\r\n\t\t\tvar byteLength = bufferViewDef.byteLength || 0;\r\n\t\t\tvar byteOffset = bufferViewDef.byteOffset || 0;\r\n\t\t\treturn buffer.slice( byteOffset, byteOffset + byteLength );\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors\r\n\t * @param {number} accessorIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadAccessor = function ( accessorIndex ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar json = this.json;\r\n\r\n\t\tvar accessorDef = this.json.accessors[ accessorIndex ];\r\n\r\n\t\tif ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {\r\n\r\n\t\t\t// Ignore empty accessors, which may be used to declare runtime\r\n\t\t\t// information about attributes coming from another source (e.g. Draco\r\n\t\t\t// compression extension).\r\n\t\t\treturn Promise.resolve( null );\r\n\r\n\t\t}\r\n\r\n\t\tvar pendingBufferViews = [];\r\n\r\n\t\tif ( accessorDef.bufferView !== undefined ) {\r\n\r\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );\r\n\r\n\t\t} else {\r\n\r\n\t\t\tpendingBufferViews.push( null );\r\n\r\n\t\t}\r\n\r\n\t\tif ( accessorDef.sparse !== undefined ) {\r\n\r\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );\r\n\t\t\tpendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( pendingBufferViews ).then( function ( bufferViews ) {\r\n\r\n\t\t\tvar bufferView = bufferViews[ 0 ];\r\n\r\n\t\t\tvar itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];\r\n\t\t\tvar TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];\r\n\r\n\t\t\t// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.\r\n\t\t\tvar elementBytes = TypedArray.BYTES_PER_ELEMENT;\r\n\t\t\tvar itemBytes = elementBytes * itemSize;\r\n\t\t\tvar byteOffset = accessorDef.byteOffset || 0;\r\n\t\t\tvar byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;\r\n\t\t\tvar normalized = accessorDef.normalized === true;\r\n\t\t\tvar array, bufferAttribute;\r\n\r\n\t\t\t// The buffer is not interleaved if the stride is the item size in bytes.\r\n\t\t\tif ( byteStride && byteStride !== itemBytes ) {\r\n\r\n\t\t\t\t// Each \"slice\" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer\r\n\t\t\t\t// This makes sure that IBA.count reflects accessor.count properly\r\n\t\t\t\tvar ibSlice = Math.floor( byteOffset / byteStride );\r\n\t\t\t\tvar ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;\r\n\t\t\t\tvar ib = parser.cache.get( ibCacheKey );\r\n\r\n\t\t\t\tif ( ! ib ) {\r\n\r\n\t\t\t\t\tarray = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );\r\n\r\n\t\t\t\t\t// Integer parameters to IB/IBA are in array elements, not bytes.\r\n\t\t\t\t\tib = new THREE.InterleavedBuffer( array, byteStride / elementBytes );\r\n\r\n\t\t\t\t\tparser.cache.add( ibCacheKey, ib );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbufferAttribute = new THREE.InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( bufferView === null ) {\r\n\r\n\t\t\t\t\tarray = new TypedArray( accessorDef.count * itemSize );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tarray = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tbufferAttribute = new THREE.BufferAttribute( array, itemSize, normalized );\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors\r\n\t\t\tif ( accessorDef.sparse !== undefined ) {\r\n\r\n\t\t\t\tvar itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;\r\n\t\t\t\tvar TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];\r\n\r\n\t\t\t\tvar byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;\r\n\t\t\t\tvar byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;\r\n\r\n\t\t\t\tvar sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );\r\n\t\t\t\tvar sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );\r\n\r\n\t\t\t\tif ( bufferView !== null ) {\r\n\r\n\t\t\t\t\t// Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.\r\n\t\t\t\t\tbufferAttribute = new THREE.BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var i = 0, il = sparseIndices.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar index = sparseIndices[ i ];\r\n\r\n\t\t\t\t\tbufferAttribute.setX( index, sparseValues[ i * itemSize ] );\r\n\t\t\t\t\tif ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );\r\n\t\t\t\t\tif ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );\r\n\t\t\t\t\tif ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );\r\n\t\t\t\t\tif ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn bufferAttribute;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures\r\n\t * @param {number} textureIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadTexture = function ( textureIndex ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar json = this.json;\r\n\t\tvar options = this.options;\r\n\t\tvar textureLoader = this.textureLoader;\r\n\r\n\t\tvar URL = window.URL || window.webkitURL;\r\n\r\n\t\tvar textureDef = json.textures[ textureIndex ];\r\n\r\n\t\tvar textureExtensions = textureDef.extensions || {};\r\n\r\n\t\tvar source;\r\n\r\n\t\tif ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {\r\n\r\n\t\t\tsource = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];\r\n\r\n\t\t} else {\r\n\r\n\t\t\tsource = json.images[ textureDef.source ];\r\n\r\n\t\t}\r\n\r\n\t\tvar sourceURI = source.uri;\r\n\t\tvar isObjectURL = false;\r\n\r\n\t\tif ( source.bufferView !== undefined ) {\r\n\r\n\t\t\t// Load binary image data from bufferView, if provided.\r\n\r\n\t\t\tsourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {\r\n\r\n\t\t\t\tisObjectURL = true;\r\n\t\t\t\tvar blob = new Blob( [ bufferView ], { type: source.mimeType } );\r\n\t\t\t\tsourceURI = URL.createObjectURL( blob );\r\n\t\t\t\treturn sourceURI;\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.resolve( sourceURI ).then( function ( sourceURI ) {\r\n\r\n\t\t\t// Load Texture resource.\r\n\r\n\t\t\tvar loader = options.manager.getHandler( sourceURI );\r\n\r\n\t\t\tif ( ! loader ) {\r\n\r\n\t\t\t\tloader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]\r\n\t\t\t\t\t? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader\r\n\t\t\t\t\t: textureLoader;\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn new Promise( function ( resolve, reject ) {\r\n\r\n\t\t\t\tloader.load( resolveURL( sourceURI, options.path ), resolve, undefined, reject );\r\n\r\n\t\t\t} );\r\n\r\n\t\t} ).then( function ( texture ) {\r\n\r\n\t\t\t// Clean up resources and configure Texture.\r\n\r\n\t\t\tif ( isObjectURL === true ) {\r\n\r\n\t\t\t\tURL.revokeObjectURL( sourceURI );\r\n\r\n\t\t\t}\r\n\r\n\t\t\ttexture.flipY = false;\r\n\r\n\t\t\tif ( textureDef.name !== undefined ) texture.name = textureDef.name;\r\n\r\n\t\t\t// Ignore unknown mime types, like DDS files.\r\n\t\t\tif ( source.mimeType in MIME_TYPE_FORMATS ) {\r\n\r\n\t\t\t\ttexture.format = MIME_TYPE_FORMATS[ source.mimeType ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar samplers = json.samplers || {};\r\n\t\t\tvar sampler = samplers[ textureDef.sampler ] || {};\r\n\r\n\t\t\ttexture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;\r\n\t\t\ttexture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.LinearMipmapLinearFilter;\r\n\t\t\ttexture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;\r\n\t\t\ttexture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;\r\n\r\n\t\t\treturn texture;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Asynchronously assigns a texture to the given material parameters.\r\n\t * @param {Object} materialParams\r\n\t * @param {string} mapName\r\n\t * @param {Object} mapDef\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) {\r\n\r\n\t\tvar parser = this;\r\n\r\n\t\treturn this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {\r\n\r\n\t\t\tif ( ! texture.isCompressedTexture ) {\r\n\r\n\t\t\t\tswitch ( mapName ) {\r\n\r\n\t\t\t\t\tcase 'aoMap':\r\n\t\t\t\t\tcase 'emissiveMap':\r\n\t\t\t\t\tcase 'metalnessMap':\r\n\t\t\t\t\tcase 'normalMap':\r\n\t\t\t\t\tcase 'roughnessMap':\r\n\t\t\t\t\t\ttexture.format = THREE.RGBFormat;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\t// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured\r\n\t\t\t// However, we will copy UV set 0 to UV set 1 on demand for aoMap\r\n\t\t\tif ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {\r\n\r\n\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.' );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {\r\n\r\n\t\t\t\tvar transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;\r\n\r\n\t\t\t\tif ( transform ) {\r\n\r\n\t\t\t\t\ttexture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterialParams[ mapName ] = texture;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Assigns final material to a Mesh, Line, or Points instance. The instance\r\n\t * already has a material (generated from the glTF material options alone)\r\n\t * but reuse of the same glTF material may require multiple threejs materials\r\n\t * to accomodate different primitive types, defines, etc. New materials will\r\n\t * be created if necessary, and reused from a cache.\r\n\t * @param {THREE.Object3D} mesh Mesh, Line, or Points instance.\r\n\t */\r\n\tGLTFParser.prototype.assignFinalMaterial = function ( mesh ) {\r\n\r\n\t\tvar geometry = mesh.geometry;\r\n\t\tvar material = mesh.material;\r\n\t\tvar extensions = this.extensions;\r\n\r\n\t\tvar useVertexTangents = geometry.attributes.tangent !== undefined;\r\n\t\tvar useVertexColors = geometry.attributes.color !== undefined;\r\n\t\tvar useFlatShading = geometry.attributes.normal === undefined;\r\n\t\tvar useSkinning = mesh.isSkinnedMesh === true;\r\n\t\tvar useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0;\r\n\t\tvar useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;\r\n\r\n\t\tif ( mesh.isPoints ) {\r\n\r\n\t\t\tvar cacheKey = 'PointsMaterial:' + material.uuid;\r\n\r\n\t\t\tvar pointsMaterial = this.cache.get( cacheKey );\r\n\r\n\t\t\tif ( ! pointsMaterial ) {\r\n\r\n\t\t\t\tpointsMaterial = new THREE.PointsMaterial();\r\n\t\t\t\tTHREE.Material.prototype.copy.call( pointsMaterial, material );\r\n\t\t\t\tpointsMaterial.color.copy( material.color );\r\n\t\t\t\tpointsMaterial.map = material.map;\r\n\t\t\t\tpointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px\r\n\r\n\t\t\t\tthis.cache.add( cacheKey, pointsMaterial );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterial = pointsMaterial;\r\n\r\n\t\t} else if ( mesh.isLine ) {\r\n\r\n\t\t\tvar cacheKey = 'LineBasicMaterial:' + material.uuid;\r\n\r\n\t\t\tvar lineMaterial = this.cache.get( cacheKey );\r\n\r\n\t\t\tif ( ! lineMaterial ) {\r\n\r\n\t\t\t\tlineMaterial = new THREE.LineBasicMaterial();\r\n\t\t\t\tTHREE.Material.prototype.copy.call( lineMaterial, material );\r\n\t\t\t\tlineMaterial.color.copy( material.color );\r\n\r\n\t\t\t\tthis.cache.add( cacheKey, lineMaterial );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterial = lineMaterial;\r\n\r\n\t\t}\r\n\r\n\t\t// Clone the material if it will be modified\r\n\t\tif ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {\r\n\r\n\t\t\tvar cacheKey = 'ClonedMaterial:' + material.uuid + ':';\r\n\r\n\t\t\tif ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';\r\n\t\t\tif ( useSkinning ) cacheKey += 'skinning:';\r\n\t\t\tif ( useVertexTangents ) cacheKey += 'vertex-tangents:';\r\n\t\t\tif ( useVertexColors ) cacheKey += 'vertex-colors:';\r\n\t\t\tif ( useFlatShading ) cacheKey += 'flat-shading:';\r\n\t\t\tif ( useMorphTargets ) cacheKey += 'morph-targets:';\r\n\t\t\tif ( useMorphNormals ) cacheKey += 'morph-normals:';\r\n\r\n\t\t\tvar cachedMaterial = this.cache.get( cacheKey );\r\n\r\n\t\t\tif ( ! cachedMaterial ) {\r\n\r\n\t\t\t\tcachedMaterial = material.isGLTFSpecularGlossinessMaterial\r\n\t\t\t\t\t? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material )\r\n\t\t\t\t\t: material.clone();\r\n\r\n\t\t\t\tif ( useSkinning ) cachedMaterial.skinning = true;\r\n\t\t\t\tif ( useVertexTangents ) cachedMaterial.vertexTangents = true;\r\n\t\t\t\tif ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;\r\n\t\t\t\tif ( useFlatShading ) cachedMaterial.flatShading = true;\r\n\t\t\t\tif ( useMorphTargets ) cachedMaterial.morphTargets = true;\r\n\t\t\t\tif ( useMorphNormals ) cachedMaterial.morphNormals = true;\r\n\r\n\t\t\t\tthis.cache.add( cacheKey, cachedMaterial );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterial = cachedMaterial;\r\n\r\n\t\t}\r\n\r\n\t\t// workarounds for mesh and geometry\r\n\r\n\t\tif ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {\r\n\r\n\t\t\tgeometry.setAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );\r\n\r\n\t\t}\r\n\r\n\t\tif ( material.isGLTFSpecularGlossinessMaterial ) {\r\n\r\n\t\t\t// for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update\r\n\t\t\tmesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms;\r\n\r\n\t\t}\r\n\r\n\t\tmesh.material = material;\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials\r\n\t * @param {number} materialIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadMaterial = function ( materialIndex ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar json = this.json;\r\n\t\tvar extensions = this.extensions;\r\n\t\tvar materialDef = json.materials[ materialIndex ];\r\n\r\n\t\tvar materialType;\r\n\t\tvar materialParams = {};\r\n\t\tvar materialExtensions = materialDef.extensions || {};\r\n\r\n\t\tvar pending = [];\r\n\r\n\t\tif ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {\r\n\r\n\t\t\tvar sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];\r\n\t\t\tmaterialType = sgExtension.getMaterialType();\r\n\t\t\tpending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );\r\n\r\n\t\t} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {\r\n\r\n\t\t\tvar kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];\r\n\t\t\tmaterialType = kmuExtension.getMaterialType();\r\n\t\t\tpending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// Specification:\r\n\t\t\t// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material\r\n\r\n\t\t\tmaterialType = THREE.MeshStandardMaterial;\r\n\r\n\t\t\tvar metallicRoughness = materialDef.pbrMetallicRoughness || {};\r\n\r\n\t\t\tmaterialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );\r\n\t\t\tmaterialParams.opacity = 1.0;\r\n\r\n\t\t\tif ( Array.isArray( metallicRoughness.baseColorFactor ) ) {\r\n\r\n\t\t\t\tvar array = metallicRoughness.baseColorFactor;\r\n\r\n\t\t\t\tmaterialParams.color.fromArray( array );\r\n\t\t\t\tmaterialParams.opacity = array[ 3 ];\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( metallicRoughness.baseColorTexture !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tmaterialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;\r\n\t\t\tmaterialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;\r\n\r\n\t\t\tif ( metallicRoughness.metallicRoughnessTexture !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );\r\n\t\t\t\tpending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( materialDef.doubleSided === true ) {\r\n\r\n\t\t\tmaterialParams.side = THREE.DoubleSide;\r\n\r\n\t\t}\r\n\r\n\t\tvar alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;\r\n\r\n\t\tif ( alphaMode === ALPHA_MODES.BLEND ) {\r\n\r\n\t\t\tmaterialParams.transparent = true;\r\n\r\n\t\t} else {\r\n\r\n\t\t\tmaterialParams.transparent = false;\r\n\r\n\t\t\tif ( alphaMode === ALPHA_MODES.MASK ) {\r\n\r\n\t\t\t\tmaterialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\r\n\r\n\t\t\tpending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );\r\n\r\n\t\t\tmaterialParams.normalScale = new THREE.Vector2( 1, 1 );\r\n\r\n\t\t\tif ( materialDef.normalTexture.scale !== undefined ) {\r\n\r\n\t\t\t\tmaterialParams.normalScale.set( materialDef.normalTexture.scale, materialDef.normalTexture.scale );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\r\n\r\n\t\t\tpending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );\r\n\r\n\t\t\tif ( materialDef.occlusionTexture.strength !== undefined ) {\r\n\r\n\t\t\t\tmaterialParams.aoMapIntensity = materialDef.occlusionTexture.strength;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( materialDef.emissiveFactor !== undefined && materialType !== THREE.MeshBasicMaterial ) {\r\n\r\n\t\t\tmaterialParams.emissive = new THREE.Color().fromArray( materialDef.emissiveFactor );\r\n\r\n\t\t}\r\n\r\n\t\tif ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {\r\n\r\n\t\t\tpending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( pending ).then( function () {\r\n\r\n\t\t\tvar material;\r\n\r\n\t\t\tif ( materialType === THREE.ShaderMaterial ) {\r\n\r\n\t\t\t\tmaterial = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tmaterial = new materialType( materialParams );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( materialDef.name !== undefined ) material.name = materialDef.name;\r\n\r\n\t\t\t// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.\r\n\t\t\tif ( material.map ) material.map.encoding = THREE.sRGBEncoding;\r\n\t\t\tif ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;\r\n\t\t\tif ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;\r\n\r\n\t\t\tassignExtrasToUserData( material, materialDef );\r\n\r\n\t\t\tif ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );\r\n\r\n\t\t\treturn material;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * @param {THREE.BufferGeometry} geometry\r\n\t * @param {GLTF.Primitive} primitiveDef\r\n\t * @param {GLTFParser} parser\r\n\t */\r\n\tfunction computeBounds( geometry, primitiveDef, parser ) {\r\n\r\n\t\tvar attributes = primitiveDef.attributes;\r\n\r\n\t\tvar box = new THREE.Box3();\r\n\r\n\t\tif ( attributes.POSITION !== undefined ) {\r\n\r\n\t\t\tvar accessor = parser.json.accessors[ attributes.POSITION ];\r\n\t\t\tvar min = accessor.min;\r\n\t\t\tvar max = accessor.max;\r\n\r\n\t\t\tbox.set(\r\n\t\t\t\tnew THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),\r\n\t\t\t\tnew THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );\r\n\r\n\t\t} else {\r\n\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tvar targets = primitiveDef.targets;\r\n\r\n\t\tif ( targets !== undefined ) {\r\n\r\n\t\t\tvar vector = new THREE.Vector3();\r\n\r\n\t\t\tfor ( var i = 0, il = targets.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar target = targets[ i ];\r\n\r\n\t\t\t\tif ( target.POSITION !== undefined ) {\r\n\r\n\t\t\t\t\tvar accessor = parser.json.accessors[ target.POSITION ];\r\n\t\t\t\t\tvar min = accessor.min;\r\n\t\t\t\t\tvar max = accessor.max;\r\n\r\n\t\t\t\t\t// we need to get max of absolute components because target weight is [-1,1]\r\n\t\t\t\t\tvector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );\r\n\t\t\t\t\tvector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );\r\n\t\t\t\t\tvector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );\r\n\r\n\t\t\t\t\tbox.expandByVector( vector );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tgeometry.boundingBox = box;\r\n\r\n\t\tvar sphere = new THREE.Sphere();\r\n\r\n\t\tbox.getCenter( sphere.center );\r\n\t\tsphere.radius = box.min.distanceTo( box.max ) / 2;\r\n\r\n\t\tgeometry.boundingSphere = sphere;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * @param {THREE.BufferGeometry} geometry\r\n\t * @param {GLTF.Primitive} primitiveDef\r\n\t * @param {GLTFParser} parser\r\n\t * @return {Promise}\r\n\t */\r\n\tfunction addPrimitiveAttributes( geometry, primitiveDef, parser ) {\r\n\r\n\t\tvar attributes = primitiveDef.attributes;\r\n\r\n\t\tvar pending = [];\r\n\r\n\t\tfunction assignAttributeAccessor( accessorIndex, attributeName ) {\r\n\r\n\t\t\treturn parser.getDependency( 'accessor', accessorIndex )\r\n\t\t\t\t.then( function ( accessor ) {\r\n\r\n\t\t\t\t\tgeometry.setAttribute( attributeName, accessor );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var gltfAttributeName in attributes ) {\r\n\r\n\t\t\tvar threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();\r\n\r\n\t\t\t// Skip attributes already provided by e.g. Draco extension.\r\n\t\t\tif ( threeAttributeName in geometry.attributes ) continue;\r\n\r\n\t\t\tpending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );\r\n\r\n\t\t}\r\n\r\n\t\tif ( primitiveDef.indices !== undefined && ! geometry.index ) {\r\n\r\n\t\t\tvar accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {\r\n\r\n\t\t\t\tgeometry.setIndex( accessor );\r\n\r\n\t\t\t} );\r\n\r\n\t\t\tpending.push( accessor );\r\n\r\n\t\t}\r\n\r\n\t\tassignExtrasToUserData( geometry, primitiveDef );\r\n\r\n\t\tcomputeBounds( geometry, primitiveDef, parser );\r\n\r\n\t\treturn Promise.all( pending ).then( function () {\r\n\r\n\t\t\treturn primitiveDef.targets !== undefined\r\n\t\t\t\t? addMorphTargets( geometry, primitiveDef.targets, parser )\r\n\t\t\t\t: geometry;\r\n\r\n\t\t} );\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * @param {THREE.BufferGeometry} geometry\r\n\t * @param {Number} drawMode\r\n\t * @return {THREE.BufferGeometry}\r\n\t */\r\n\tfunction toTrianglesDrawMode( geometry, drawMode ) {\r\n\r\n\t\tvar index = geometry.getIndex();\r\n\r\n\t\t// generate index if not present\r\n\r\n\t\tif ( index === null ) {\r\n\r\n\t\t\tvar indices = [];\r\n\r\n\t\t\tvar position = geometry.getAttribute( 'position' );\r\n\r\n\t\t\tif ( position !== undefined ) {\r\n\r\n\t\t\t\tfor ( var i = 0; i < position.count; i ++ ) {\r\n\r\n\t\t\t\t\tindices.push( i );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tgeometry.setIndex( indices );\r\n\t\t\t\tindex = geometry.getIndex();\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tconsole.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );\r\n\t\t\t\treturn geometry;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\t//\r\n\r\n\t\tvar numberOfTriangles = index.count - 2;\r\n\t\tvar newIndices = [];\r\n\r\n\t\tif ( drawMode === THREE.TriangleFanDrawMode ) {\r\n\r\n\t\t\t// gl.TRIANGLE_FAN\r\n\r\n\t\t\tfor ( var i = 1; i <= numberOfTriangles; i ++ ) {\r\n\r\n\t\t\t\tnewIndices.push( index.getX( 0 ) );\r\n\t\t\t\tnewIndices.push( index.getX( i ) );\r\n\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t} else {\r\n\r\n\t\t\t// gl.TRIANGLE_STRIP\r\n\r\n\t\t\tfor ( var i = 0; i < numberOfTriangles; i ++ ) {\r\n\r\n\t\t\t\tif ( i % 2 === 0 ) {\r\n\r\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\r\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\r\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\r\n\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tnewIndices.push( index.getX( i + 2 ) );\r\n\t\t\t\t\tnewIndices.push( index.getX( i + 1 ) );\r\n\t\t\t\t\tnewIndices.push( index.getX( i ) );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tif ( ( newIndices.length / 3 ) !== numberOfTriangles ) {\r\n\r\n\t\t\tconsole.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );\r\n\r\n\t\t}\r\n\r\n\t\t// build final geometry\r\n\r\n\t\tvar newGeometry = geometry.clone();\r\n\t\tnewGeometry.setIndex( newIndices );\r\n\r\n\t\treturn newGeometry;\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry\r\n\t *\r\n\t * Creates BufferGeometries from primitives.\r\n\t *\r\n\t * @param {Array} primitives\r\n\t * @return {Promise>}\r\n\t */\r\n\tGLTFParser.prototype.loadGeometries = function ( primitives ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar extensions = this.extensions;\r\n\t\tvar cache = this.primitiveCache;\r\n\r\n\t\tfunction createDracoPrimitive( primitive ) {\r\n\r\n\t\t\treturn extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]\r\n\t\t\t\t.decodePrimitive( primitive, parser )\r\n\t\t\t\t.then( function ( geometry ) {\r\n\r\n\t\t\t\t\treturn addPrimitiveAttributes( geometry, primitive, parser );\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\tvar pending = [];\r\n\r\n\t\tfor ( var i = 0, il = primitives.length; i < il; i ++ ) {\r\n\r\n\t\t\tvar primitive = primitives[ i ];\r\n\t\t\tvar cacheKey = createPrimitiveKey( primitive );\r\n\r\n\t\t\t// See if we've already created this geometry\r\n\t\t\tvar cached = cache[ cacheKey ];\r\n\r\n\t\t\tif ( cached ) {\r\n\r\n\t\t\t\t// Use the cached geometry if it exists\r\n\t\t\t\tpending.push( cached.promise );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tvar geometryPromise;\r\n\r\n\t\t\t\tif ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {\r\n\r\n\t\t\t\t\t// Use DRACO geometry if available\r\n\t\t\t\t\tgeometryPromise = createDracoPrimitive( primitive );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\t// Otherwise create a new geometry\r\n\t\t\t\t\tgeometryPromise = addPrimitiveAttributes( new THREE.BufferGeometry(), primitive, parser );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\t// Cache this geometry\r\n\t\t\t\tcache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };\r\n\r\n\t\t\t\tpending.push( geometryPromise );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( pending );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes\r\n\t * @param {number} meshIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadMesh = function ( meshIndex ) {\r\n\r\n\t\tvar parser = this;\r\n\t\tvar json = this.json;\r\n\r\n\t\tvar meshDef = json.meshes[ meshIndex ];\r\n\t\tvar primitives = meshDef.primitives;\r\n\r\n\t\tvar pending = [];\r\n\r\n\t\tfor ( var i = 0, il = primitives.length; i < il; i ++ ) {\r\n\r\n\t\t\tvar material = primitives[ i ].material === undefined\r\n\t\t\t\t? createDefaultMaterial( this.cache )\r\n\t\t\t\t: this.getDependency( 'material', primitives[ i ].material );\r\n\r\n\t\t\tpending.push( material );\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( pending ).then( function ( originalMaterials ) {\r\n\r\n\t\t\treturn parser.loadGeometries( primitives ).then( function ( geometries ) {\r\n\r\n\t\t\t\tvar meshes = [];\r\n\r\n\t\t\t\tfor ( var i = 0, il = geometries.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tvar geometry = geometries[ i ];\r\n\t\t\t\t\tvar primitive = primitives[ i ];\r\n\r\n\t\t\t\t\t// 1. create Mesh\r\n\r\n\t\t\t\t\tvar mesh;\r\n\r\n\t\t\t\t\tvar material = originalMaterials[ i ];\r\n\r\n\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||\r\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||\r\n\t\t\t\t\t\tprimitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||\r\n\t\t\t\t\t\tprimitive.mode === undefined ) {\r\n\r\n\t\t\t\t\t\t// .isSkinnedMesh isn't in glTF spec. See .markDefs()\r\n\t\t\t\t\t\tmesh = meshDef.isSkinnedMesh === true\r\n\t\t\t\t\t\t\t? new THREE.SkinnedMesh( geometry, material )\r\n\t\t\t\t\t\t\t: new THREE.Mesh( geometry, material );\r\n\r\n\t\t\t\t\t\tif ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {\r\n\r\n\t\t\t\t\t\t\t// we normalize floating point skin weight array to fix malformed assets (see #15319)\r\n\t\t\t\t\t\t\t// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs\r\n\t\t\t\t\t\t\tmesh.normalizeSkinWeights();\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {\r\n\r\n\t\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );\r\n\r\n\t\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {\r\n\r\n\t\t\t\t\t\t\tmesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {\r\n\r\n\t\t\t\t\t\tmesh = new THREE.LineSegments( geometry, material );\r\n\r\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {\r\n\r\n\t\t\t\t\t\tmesh = new THREE.Line( geometry, material );\r\n\r\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {\r\n\r\n\t\t\t\t\t\tmesh = new THREE.LineLoop( geometry, material );\r\n\r\n\t\t\t\t\t} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {\r\n\r\n\t\t\t\t\t\tmesh = new THREE.Points( geometry, material );\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {\r\n\r\n\t\t\t\t\t\tupdateMorphTargets( mesh, meshDef );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tmesh.name = meshDef.name || ( 'mesh_' + meshIndex );\r\n\r\n\t\t\t\t\tif ( geometries.length > 1 ) mesh.name += '_' + i;\r\n\r\n\t\t\t\t\tassignExtrasToUserData( mesh, meshDef );\r\n\r\n\t\t\t\t\tparser.assignFinalMaterial( mesh );\r\n\r\n\t\t\t\t\tmeshes.push( mesh );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( meshes.length === 1 ) {\r\n\r\n\t\t\t\t\treturn meshes[ 0 ];\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar group = new THREE.Group();\r\n\r\n\t\t\t\tfor ( var i = 0, il = meshes.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tgroup.add( meshes[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn group;\r\n\r\n\t\t\t} );\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras\r\n\t * @param {number} cameraIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadCamera = function ( cameraIndex ) {\r\n\r\n\t\tvar camera;\r\n\t\tvar cameraDef = this.json.cameras[ cameraIndex ];\r\n\t\tvar params = cameraDef[ cameraDef.type ];\r\n\r\n\t\tif ( ! params ) {\r\n\r\n\t\t\tconsole.warn( 'THREE.GLTFLoader: Missing camera parameters.' );\r\n\t\t\treturn;\r\n\r\n\t\t}\r\n\r\n\t\tif ( cameraDef.type === 'perspective' ) {\r\n\r\n\t\t\tcamera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );\r\n\r\n\t\t} else if ( cameraDef.type === 'orthographic' ) {\r\n\r\n\t\t\tcamera = new THREE.OrthographicCamera( params.xmag / - 2, params.xmag / 2, params.ymag / 2, params.ymag / - 2, params.znear, params.zfar );\r\n\r\n\t\t}\r\n\r\n\t\tif ( cameraDef.name !== undefined ) camera.name = cameraDef.name;\r\n\r\n\t\tassignExtrasToUserData( camera, cameraDef );\r\n\r\n\t\treturn Promise.resolve( camera );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins\r\n\t * @param {number} skinIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadSkin = function ( skinIndex ) {\r\n\r\n\t\tvar skinDef = this.json.skins[ skinIndex ];\r\n\r\n\t\tvar skinEntry = { joints: skinDef.joints };\r\n\r\n\t\tif ( skinDef.inverseBindMatrices === undefined ) {\r\n\r\n\t\t\treturn Promise.resolve( skinEntry );\r\n\r\n\t\t}\r\n\r\n\t\treturn this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {\r\n\r\n\t\t\tskinEntry.inverseBindMatrices = accessor;\r\n\r\n\t\t\treturn skinEntry;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations\r\n\t * @param {number} animationIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadAnimation = function ( animationIndex ) {\r\n\r\n\t\tvar json = this.json;\r\n\r\n\t\tvar animationDef = json.animations[ animationIndex ];\r\n\r\n\t\tvar pendingNodes = [];\r\n\t\tvar pendingInputAccessors = [];\r\n\t\tvar pendingOutputAccessors = [];\r\n\t\tvar pendingSamplers = [];\r\n\t\tvar pendingTargets = [];\r\n\r\n\t\tfor ( var i = 0, il = animationDef.channels.length; i < il; i ++ ) {\r\n\r\n\t\t\tvar channel = animationDef.channels[ i ];\r\n\t\t\tvar sampler = animationDef.samplers[ channel.sampler ];\r\n\t\t\tvar target = channel.target;\r\n\t\t\tvar name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.\r\n\t\t\tvar input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;\r\n\t\t\tvar output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;\r\n\r\n\t\t\tpendingNodes.push( this.getDependency( 'node', name ) );\r\n\t\t\tpendingInputAccessors.push( this.getDependency( 'accessor', input ) );\r\n\t\t\tpendingOutputAccessors.push( this.getDependency( 'accessor', output ) );\r\n\t\t\tpendingSamplers.push( sampler );\r\n\t\t\tpendingTargets.push( target );\r\n\r\n\t\t}\r\n\r\n\t\treturn Promise.all( [\r\n\r\n\t\t\tPromise.all( pendingNodes ),\r\n\t\t\tPromise.all( pendingInputAccessors ),\r\n\t\t\tPromise.all( pendingOutputAccessors ),\r\n\t\t\tPromise.all( pendingSamplers ),\r\n\t\t\tPromise.all( pendingTargets )\r\n\r\n\t\t] ).then( function ( dependencies ) {\r\n\r\n\t\t\tvar nodes = dependencies[ 0 ];\r\n\t\t\tvar inputAccessors = dependencies[ 1 ];\r\n\t\t\tvar outputAccessors = dependencies[ 2 ];\r\n\t\t\tvar samplers = dependencies[ 3 ];\r\n\t\t\tvar targets = dependencies[ 4 ];\r\n\r\n\t\t\tvar tracks = [];\r\n\r\n\t\t\tfor ( var i = 0, il = nodes.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tvar node = nodes[ i ];\r\n\t\t\t\tvar inputAccessor = inputAccessors[ i ];\r\n\t\t\t\tvar outputAccessor = outputAccessors[ i ];\r\n\t\t\t\tvar sampler = samplers[ i ];\r\n\t\t\t\tvar target = targets[ i ];\r\n\r\n\t\t\t\tif ( node === undefined ) continue;\r\n\r\n\t\t\t\tnode.updateMatrix();\r\n\t\t\t\tnode.matrixAutoUpdate = true;\r\n\r\n\t\t\t\tvar TypedKeyframeTrack;\r\n\r\n\t\t\t\tswitch ( PATH_PROPERTIES[ target.path ] ) {\r\n\r\n\t\t\t\t\tcase PATH_PROPERTIES.weights:\r\n\r\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.NumberKeyframeTrack;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase PATH_PROPERTIES.rotation:\r\n\r\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.QuaternionKeyframeTrack;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tcase PATH_PROPERTIES.position:\r\n\t\t\t\t\tcase PATH_PROPERTIES.scale:\r\n\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\tTypedKeyframeTrack = THREE.VectorKeyframeTrack;\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar targetName = node.name ? node.name : node.uuid;\r\n\r\n\t\t\t\tvar interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;\r\n\r\n\t\t\t\tvar targetNames = [];\r\n\r\n\t\t\t\tif ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {\r\n\r\n\t\t\t\t\t// Node may be a THREE.Group (glTF mesh with several primitives) or a THREE.Mesh.\r\n\t\t\t\t\tnode.traverse( function ( object ) {\r\n\r\n\t\t\t\t\t\tif ( object.isMesh === true && object.morphTargetInfluences ) {\r\n\r\n\t\t\t\t\t\t\ttargetNames.push( object.name ? object.name : object.uuid );\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\ttargetNames.push( targetName );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tvar outputArray = outputAccessor.array;\r\n\r\n\t\t\t\tif ( outputAccessor.normalized ) {\r\n\r\n\t\t\t\t\tvar scale;\r\n\r\n\t\t\t\t\tif ( outputArray.constructor === Int8Array ) {\r\n\r\n\t\t\t\t\t\tscale = 1 / 127;\r\n\r\n\t\t\t\t\t} else if ( outputArray.constructor === Uint8Array ) {\r\n\r\n\t\t\t\t\t\tscale = 1 / 255;\r\n\r\n\t\t\t\t\t} else if ( outputArray.constructor == Int16Array ) {\r\n\r\n\t\t\t\t\t\tscale = 1 / 32767;\r\n\r\n\t\t\t\t\t} else if ( outputArray.constructor === Uint16Array ) {\r\n\r\n\t\t\t\t\t\tscale = 1 / 65535;\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tthrow new Error( 'THREE.GLTFLoader: Unsupported output accessor component type.' );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tvar scaled = new Float32Array( outputArray.length );\r\n\r\n\t\t\t\t\tfor ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\tscaled[ j ] = outputArray[ j ] * scale;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\toutputArray = scaled;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfor ( var j = 0, jl = targetNames.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\tvar track = new TypedKeyframeTrack(\r\n\t\t\t\t\t\ttargetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],\r\n\t\t\t\t\t\tinputAccessor.array,\r\n\t\t\t\t\t\toutputArray,\r\n\t\t\t\t\t\tinterpolation\r\n\t\t\t\t\t);\r\n\r\n\t\t\t\t\t// Override interpolation with custom factory method.\r\n\t\t\t\t\tif ( sampler.interpolation === 'CUBICSPLINE' ) {\r\n\r\n\t\t\t\t\t\ttrack.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {\r\n\r\n\t\t\t\t\t\t\t// A CUBICSPLINE keyframe in glTF has three output values for each input value,\r\n\t\t\t\t\t\t\t// representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()\r\n\t\t\t\t\t\t\t// must be divided by three to get the interpolant's sampleSize argument.\r\n\r\n\t\t\t\t\t\t\treturn new GLTFCubicSplineInterpolant( this.times, this.values, this.getValueSize() / 3, result );\r\n\r\n\t\t\t\t\t\t};\r\n\r\n\t\t\t\t\t\t// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.\r\n\t\t\t\t\t\ttrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ttracks.push( track );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar name = animationDef.name !== undefined ? animationDef.name : 'animation_' + animationIndex;\r\n\r\n\t\t\treturn new THREE.AnimationClip( name, undefined, tracks );\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy\r\n\t * @param {number} nodeIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadNode = function ( nodeIndex ) {\r\n\r\n\t\tvar json = this.json;\r\n\t\tvar extensions = this.extensions;\r\n\t\tvar parser = this;\r\n\r\n\t\tvar meshReferences = json.meshReferences;\r\n\t\tvar meshUses = json.meshUses;\r\n\r\n\t\tvar nodeDef = json.nodes[ nodeIndex ];\r\n\r\n\t\treturn ( function () {\r\n\r\n\t\t\tvar pending = [];\r\n\r\n\t\t\tif ( nodeDef.mesh !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {\r\n\r\n\t\t\t\t\tvar node;\r\n\r\n\t\t\t\t\tif ( meshReferences[ nodeDef.mesh ] > 1 ) {\r\n\r\n\t\t\t\t\t\tvar instanceNum = meshUses[ nodeDef.mesh ] ++;\r\n\r\n\t\t\t\t\t\tnode = mesh.clone();\r\n\t\t\t\t\t\tnode.name += '_instance_' + instanceNum;\r\n\r\n\t\t\t\t\t\t// onBeforeRender copy for Specular-Glossiness\r\n\t\t\t\t\t\tnode.onBeforeRender = mesh.onBeforeRender;\r\n\r\n\t\t\t\t\t\tfor ( var i = 0, il = node.children.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\tnode.children[ i ].name += '_instance_' + instanceNum;\r\n\t\t\t\t\t\t\tnode.children[ i ].onBeforeRender = mesh.children[ i ].onBeforeRender;\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\tnode = mesh;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// if weights are provided on the node, override weights on the mesh.\r\n\t\t\t\t\tif ( nodeDef.weights !== undefined ) {\r\n\r\n\t\t\t\t\t\tnode.traverse( function ( o ) {\r\n\r\n\t\t\t\t\t\t\tif ( ! o.isMesh ) return;\r\n\r\n\t\t\t\t\t\t\tfor ( var i = 0, il = nodeDef.weights.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\t\t\to.morphTargetInfluences[ i ] = nodeDef.weights[ i ];\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t} );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn node;\r\n\r\n\t\t\t\t} ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( nodeDef.camera !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.getDependency( 'camera', nodeDef.camera ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( nodeDef.extensions\r\n\t\t\t\t&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]\r\n\t\t\t\t&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {\r\n\r\n\t\t\t\tpending.push( parser.getDependency( 'light', nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn Promise.all( pending );\r\n\r\n\t\t}() ).then( function ( objects ) {\r\n\r\n\t\t\tvar node;\r\n\r\n\t\t\t// .isBone isn't in glTF spec. See .markDefs\r\n\t\t\tif ( nodeDef.isBone === true ) {\r\n\r\n\t\t\t\tnode = new THREE.Bone();\r\n\r\n\t\t\t} else if ( objects.length > 1 ) {\r\n\r\n\t\t\t\tnode = new THREE.Group();\r\n\r\n\t\t\t} else if ( objects.length === 1 ) {\r\n\r\n\t\t\t\tnode = objects[ 0 ];\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tnode = new THREE.Object3D();\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( node !== objects[ 0 ] ) {\r\n\r\n\t\t\t\tfor ( var i = 0, il = objects.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\tnode.add( objects[ i ] );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\tif ( nodeDef.name !== undefined ) {\r\n\r\n\t\t\t\tnode.userData.name = nodeDef.name;\r\n\t\t\t\tnode.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );\r\n\r\n\t\t\t}\r\n\r\n\t\t\tassignExtrasToUserData( node, nodeDef );\r\n\r\n\t\t\tif ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );\r\n\r\n\t\t\tif ( nodeDef.matrix !== undefined ) {\r\n\r\n\t\t\t\tvar matrix = new THREE.Matrix4();\r\n\t\t\t\tmatrix.fromArray( nodeDef.matrix );\r\n\t\t\t\tnode.applyMatrix( matrix );\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( nodeDef.translation !== undefined ) {\r\n\r\n\t\t\t\t\tnode.position.fromArray( nodeDef.translation );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( nodeDef.rotation !== undefined ) {\r\n\r\n\t\t\t\t\tnode.quaternion.fromArray( nodeDef.rotation );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( nodeDef.scale !== undefined ) {\r\n\r\n\t\t\t\t\tnode.scale.fromArray( nodeDef.scale );\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn node;\r\n\r\n\t\t} );\r\n\r\n\t};\r\n\r\n\t/**\r\n\t * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes\r\n\t * @param {number} sceneIndex\r\n\t * @return {Promise}\r\n\t */\r\n\tGLTFParser.prototype.loadScene = function () {\r\n\r\n\t\t// scene node hierachy builder\r\n\r\n\t\tfunction buildNodeHierachy( nodeId, parentObject, json, parser ) {\r\n\r\n\t\t\tvar nodeDef = json.nodes[ nodeId ];\r\n\r\n\t\t\treturn parser.getDependency( 'node', nodeId ).then( function ( node ) {\r\n\r\n\t\t\t\tif ( nodeDef.skin === undefined ) return node;\r\n\r\n\t\t\t\t// build skeleton here as well\r\n\r\n\t\t\t\tvar skinEntry;\r\n\r\n\t\t\t\treturn parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {\r\n\r\n\t\t\t\t\tskinEntry = skin;\r\n\r\n\t\t\t\t\tvar pendingJoints = [];\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = skinEntry.joints.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tpendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn Promise.all( pendingJoints );\r\n\r\n\t\t\t\t} ).then( function ( jointNodes ) {\r\n\r\n\t\t\t\t\tnode.traverse( function ( mesh ) {\r\n\r\n\t\t\t\t\t\tif ( ! mesh.isMesh ) return;\r\n\r\n\t\t\t\t\t\tvar bones = [];\r\n\t\t\t\t\t\tvar boneInverses = [];\r\n\r\n\t\t\t\t\t\tfor ( var j = 0, jl = jointNodes.length; j < jl; j ++ ) {\r\n\r\n\t\t\t\t\t\t\tvar jointNode = jointNodes[ j ];\r\n\r\n\t\t\t\t\t\t\tif ( jointNode ) {\r\n\r\n\t\t\t\t\t\t\t\tbones.push( jointNode );\r\n\r\n\t\t\t\t\t\t\t\tvar mat = new THREE.Matrix4();\r\n\r\n\t\t\t\t\t\t\t\tif ( skinEntry.inverseBindMatrices !== undefined ) {\r\n\r\n\t\t\t\t\t\t\t\t\tmat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );\r\n\r\n\t\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t\t\tboneInverses.push( mat );\r\n\r\n\t\t\t\t\t\t\t} else {\r\n\r\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.GLTFLoader: Joint \"%s\" could not be found.', skinEntry.joints[ j ] );\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tmesh.bind( new THREE.Skeleton( bones, boneInverses ), mesh.matrixWorld );\r\n\r\n\t\t\t\t\t} );\r\n\r\n\t\t\t\t\treturn node;\r\n\r\n\t\t\t\t} );\r\n\r\n\t\t\t} ).then( function ( node ) {\r\n\r\n\t\t\t\t// build node hierachy\r\n\r\n\t\t\t\tparentObject.add( node );\r\n\r\n\t\t\t\tvar pending = [];\r\n\r\n\t\t\t\tif ( nodeDef.children ) {\r\n\r\n\t\t\t\t\tvar children = nodeDef.children;\r\n\r\n\t\t\t\t\tfor ( var i = 0, il = children.length; i < il; i ++ ) {\r\n\r\n\t\t\t\t\t\tvar child = children[ i ];\r\n\t\t\t\t\t\tpending.push( buildNodeHierachy( child, node, json, parser ) );\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\treturn Promise.all( pending );\r\n\r\n\t\t\t} );\r\n\r\n\t\t}\r\n\r\n\t\treturn function loadScene( sceneIndex ) {\r\n\r\n\t\t\tvar json = this.json;\r\n\t\t\tvar extensions = this.extensions;\r\n\t\t\tvar sceneDef = this.json.scenes[ sceneIndex ];\r\n\t\t\tvar parser = this;\r\n\r\n\t\t\tvar scene = new THREE.Scene();\r\n\t\t\tif ( sceneDef.name !== undefined ) scene.name = sceneDef.name;\r\n\r\n\t\t\tassignExtrasToUserData( scene, sceneDef );\r\n\r\n\t\t\tif ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );\r\n\r\n\t\t\tvar nodeIds = sceneDef.nodes || [];\r\n\r\n\t\t\tvar pending = [];\r\n\r\n\t\t\tfor ( var i = 0, il = nodeIds.length; i < il; i ++ ) {\r\n\r\n\t\t\t\tpending.push( buildNodeHierachy( nodeIds[ i ], scene, json, parser ) );\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn Promise.all( pending ).then( function () {\r\n\r\n\t\t\t\treturn scene;\r\n\r\n\t\t\t} );\r\n\r\n\t\t};\r\n\r\n\t}();\r\n\r\n\treturn GLTFLoader;\r\n\r\n} )();\r\n", "/**\r\n * Loads a Wavefront .mtl file specifying materials\r\n *\r\n * @author angelxuanchang\r\n */\r\n\r\nTHREE.MTLLoader = function ( manager ) {\r\n\r\n\tTHREE.Loader.call( this, manager );\r\n\r\n};\r\n\r\nTHREE.MTLLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {\r\n\r\n\tconstructor: THREE.MTLLoader,\r\n\r\n\t/**\r\n\t * Loads and parses a MTL asset from a URL.\r\n\t *\r\n\t * @param {String} url - URL to the MTL file.\r\n\t * @param {Function} [onLoad] - Callback invoked with the loaded object.\r\n\t * @param {Function} [onProgress] - Callback for download progress.\r\n\t * @param {Function} [onError] - Callback for download errors.\r\n\t *\r\n\t * @see setPath setResourcePath\r\n\t *\r\n\t * @note In order for relative texture references to resolve correctly\r\n\t * you must call setResourcePath() explicitly prior to load.\r\n\t */\r\n\tload: function ( url, onLoad, onProgress, onError ) {\r\n\r\n\t\tvar scope = this;\r\n\r\n\t\tvar path = ( this.path === '' ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;\r\n\r\n\t\tvar loader = new THREE.FileLoader( this.manager );\r\n\t\tloader.setPath( this.path );\r\n\t\tloader.load( url, function ( text ) {\r\n\r\n\t\t\tonLoad( scope.parse( text, path ) );\r\n\r\n\t\t}, onProgress, onError );\r\n\r\n\t},\r\n\r\n\tsetMaterialOptions: function ( value ) {\r\n\r\n\t\tthis.materialOptions = value;\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\t/**\r\n\t * Parses a MTL file.\r\n\t *\r\n\t * @param {String} text - Content of MTL file\r\n\t * @return {THREE.MTLLoader.MaterialCreator}\r\n\t *\r\n\t * @see setPath setResourcePath\r\n\t *\r\n\t * @note In order for relative texture references to resolve correctly\r\n\t * you must call setResourcePath() explicitly prior to parse.\r\n\t */\r\n\tparse: function ( text, path ) {\r\n\r\n\t\tvar lines = text.split( '\\n' );\r\n\t\tvar info = {};\r\n\t\tvar delimiter_pattern = /\\s+/;\r\n\t\tvar materialsInfo = {};\r\n\r\n\t\tfor ( var i = 0; i < lines.length; i ++ ) {\r\n\r\n\t\t\tvar line = lines[ i ];\r\n\t\t\tline = line.trim();\r\n\r\n\t\t\tif ( line.length === 0 || line.charAt( 0 ) === '#' ) {\r\n\r\n\t\t\t\t// Blank line or comment ignore\r\n\t\t\t\tcontinue;\r\n\r\n\t\t\t}\r\n\r\n\t\t\tvar pos = line.indexOf( ' ' );\r\n\r\n\t\t\tvar key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;\r\n\t\t\tkey = key.toLowerCase();\r\n\r\n\t\t\tvar value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';\r\n\t\t\tvalue = value.trim();\r\n\r\n\t\t\tif ( key === 'newmtl' ) {\r\n\r\n\t\t\t\t// New material\r\n\r\n\t\t\t\tinfo = { name: value };\r\n\t\t\t\tmaterialsInfo[ value ] = info;\r\n\r\n\t\t\t} else {\r\n\r\n\t\t\t\tif ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {\r\n\r\n\t\t\t\t\tvar ss = value.split( delimiter_pattern, 3 );\r\n\t\t\t\t\tinfo[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];\r\n\r\n\t\t\t\t} else {\r\n\r\n\t\t\t\t\tinfo[ key ] = value;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tvar materialCreator = new THREE.MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );\r\n\t\tmaterialCreator.setCrossOrigin( this.crossOrigin );\r\n\t\tmaterialCreator.setManager( this.manager );\r\n\t\tmaterialCreator.setMaterials( materialsInfo );\r\n\t\treturn materialCreator;\r\n\r\n\t}\r\n\r\n} );\r\n\r\n/**\r\n * Create a new THREE.MTLLoader.MaterialCreator\r\n * @param baseUrl - Url relative to which textures are loaded\r\n * @param options - Set of options on how to construct the materials\r\n * side: Which side to apply the material\r\n * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide\r\n * wrap: What type of wrapping to apply for textures\r\n * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping\r\n * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255\r\n * Default: false, assumed to be already normalized\r\n * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's\r\n * Default: false\r\n * @constructor\r\n */\r\n\r\nTHREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {\r\n\r\n\tthis.baseUrl = baseUrl || '';\r\n\tthis.options = options;\r\n\tthis.materialsInfo = {};\r\n\tthis.materials = {};\r\n\tthis.materialsArray = [];\r\n\tthis.nameLookup = {};\r\n\r\n\tthis.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;\r\n\tthis.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;\r\n\r\n};\r\n\r\nTHREE.MTLLoader.MaterialCreator.prototype = {\r\n\r\n\tconstructor: THREE.MTLLoader.MaterialCreator,\r\n\r\n\tcrossOrigin: 'anonymous',\r\n\r\n\tsetCrossOrigin: function ( value ) {\r\n\r\n\t\tthis.crossOrigin = value;\r\n\t\treturn this;\r\n\r\n\t},\r\n\r\n\tsetManager: function ( value ) {\r\n\r\n\t\tthis.manager = value;\r\n\r\n\t},\r\n\r\n\tsetMaterials: function ( materialsInfo ) {\r\n\r\n\t\tthis.materialsInfo = this.convert( materialsInfo );\r\n\t\tthis.materials = {};\r\n\t\tthis.materialsArray = [];\r\n\t\tthis.nameLookup = {};\r\n\r\n\t},\r\n\r\n\tconvert: function ( materialsInfo ) {\r\n\r\n\t\tif ( ! this.options ) return materialsInfo;\r\n\r\n\t\tvar converted = {};\r\n\r\n\t\tfor ( var mn in materialsInfo ) {\r\n\r\n\t\t\t// Convert materials info into normalized form based on options\r\n\r\n\t\t\tvar mat = materialsInfo[ mn ];\r\n\r\n\t\t\tvar covmat = {};\r\n\r\n\t\t\tconverted[ mn ] = covmat;\r\n\r\n\t\t\tfor ( var prop in mat ) {\r\n\r\n\t\t\t\tvar save = true;\r\n\t\t\t\tvar value = mat[ prop ];\r\n\t\t\t\tvar lprop = prop.toLowerCase();\r\n\r\n\t\t\t\tswitch ( lprop ) {\r\n\r\n\t\t\t\t\tcase 'kd':\r\n\t\t\t\t\tcase 'ka':\r\n\t\t\t\t\tcase 'ks':\r\n\r\n\t\t\t\t\t\t// Diffuse color (color under white light) using RGB values\r\n\r\n\t\t\t\t\t\tif ( this.options && this.options.normalizeRGB ) {\r\n\r\n\t\t\t\t\t\t\tvalue = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tif ( this.options && this.options.ignoreZeroRGBs ) {\r\n\r\n\t\t\t\t\t\t\tif ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {\r\n\r\n\t\t\t\t\t\t\t\t// ignore\r\n\r\n\t\t\t\t\t\t\t\tsave = false;\r\n\r\n\t\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t\tdefault:\r\n\r\n\t\t\t\t\t\tbreak;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif ( save ) {\r\n\r\n\t\t\t\t\tcovmat[ lprop ] = value;\r\n\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\treturn converted;\r\n\r\n\t},\r\n\r\n\tpreload: function () {\r\n\r\n\t\tfor ( var mn in this.materialsInfo ) {\r\n\r\n\t\t\tthis.create( mn );\r\n\r\n\t\t}\r\n\r\n\t},\r\n\r\n\tgetIndex: function ( materialName ) {\r\n\r\n\t\treturn this.nameLookup[ materialName ];\r\n\r\n\t},\r\n\r\n\tgetAsArray: function () {\r\n\r\n\t\tvar index = 0;\r\n\r\n\t\tfor ( var mn in this.materialsInfo ) {\r\n\r\n\t\t\tthis.materialsArray[ index ] = this.create( mn );\r\n\t\t\tthis.nameLookup[ mn ] = index;\r\n\t\t\tindex ++;\r\n\r\n\t\t}\r\n\r\n\t\treturn this.materialsArray;\r\n\r\n\t},\r\n\r\n\tcreate: function ( materialName ) {\r\n\r\n\t\tif ( this.materials[ materialName ] === undefined ) {\r\n\r\n\t\t\tthis.createMaterial_( materialName );\r\n\r\n\t\t}\r\n\r\n\t\treturn this.materials[ materialName ];\r\n\r\n\t},\r\n\r\n\tcreateMaterial_: function ( materialName ) {\r\n\r\n\t\t// Create material\r\n\r\n\t\tvar scope = this;\r\n\t\tvar mat = this.materialsInfo[ materialName ];\r\n\t\tvar params = {\r\n\r\n\t\t\tname: materialName,\r\n\t\t\tside: this.side\r\n\r\n\t\t};\r\n\r\n\t\tfunction resolveURL( baseUrl, url ) {\r\n\r\n\t\t\tif ( typeof url !== 'string' || url === '' )\r\n\t\t\t\treturn '';\r\n\r\n\t\t\t// Absolute URL\r\n\t\t\tif ( /^https?:\\/\\//i.test( url ) ) return url;\r\n\r\n\t\t\treturn baseUrl + url;\r\n\r\n\t\t}\r\n\r\n\t\tfunction setMapForType( mapType, value ) {\r\n\r\n\t\t\tif ( params[ mapType ] ) return; // Keep the first encountered texture\r\n\r\n\t\t\tvar texParams = scope.getTextureParams( value, params );\r\n\t\t\tvar map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );\r\n\r\n\t\t\tmap.repeat.copy( texParams.scale );\r\n\t\t\tmap.offset.copy( texParams.offset );\r\n\r\n\t\t\tmap.wrapS = scope.wrap;\r\n\t\t\tmap.wrapT = scope.wrap;\r\n\r\n\t\t\tparams[ mapType ] = map;\r\n\r\n\t\t}\r\n\r\n\t\tfor ( var prop in mat ) {\r\n\r\n\t\t\tvar value = mat[ prop ];\r\n\t\t\tvar n;\r\n\r\n\t\t\tif ( value === '' ) continue;\r\n\r\n\t\t\tswitch ( prop.toLowerCase() ) {\r\n\r\n\t\t\t\t// Ns is material specular exponent\r\n\r\n\t\t\t\tcase 'kd':\r\n\r\n\t\t\t\t\t// Diffuse color (color under white light) using RGB values\r\n\r\n\t\t\t\t\tparams.color = new THREE.Color().fromArray( value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'ks':\r\n\r\n\t\t\t\t\t// Specular color (color when light is reflected from shiny surface) using RGB values\r\n\t\t\t\t\tparams.specular = new THREE.Color().fromArray( value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'ke':\r\n\r\n\t\t\t\t\t// Emissive using RGB values\r\n\t\t\t\t\tparams.emissive = new THREE.Color().fromArray( value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'map_kd':\r\n\r\n\t\t\t\t\t// Diffuse texture map\r\n\r\n\t\t\t\t\tsetMapForType( \"map\", value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'map_ks':\r\n\r\n\t\t\t\t\t// Specular map\r\n\r\n\t\t\t\t\tsetMapForType( \"specularMap\", value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'map_ke':\r\n\r\n\t\t\t\t\t// Emissive map\r\n\r\n\t\t\t\t\tsetMapForType( \"emissiveMap\", value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'norm':\r\n\r\n\t\t\t\t\tsetMapForType( \"normalMap\", value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'map_bump':\r\n\t\t\t\tcase 'bump':\r\n\r\n\t\t\t\t\t// Bump texture map\r\n\r\n\t\t\t\t\tsetMapForType( \"bumpMap\", value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'map_d':\r\n\r\n\t\t\t\t\t// Alpha map\r\n\r\n\t\t\t\t\tsetMapForType( \"alphaMap\", value );\r\n\t\t\t\t\tparams.transparent = true;\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'ns':\r\n\r\n\t\t\t\t\t// The specular exponent (defines the focus of the specular highlight)\r\n\t\t\t\t\t// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.\r\n\r\n\t\t\t\t\tparams.shininess = parseFloat( value );\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'd':\r\n\t\t\t\t\tn = parseFloat( value );\r\n\r\n\t\t\t\t\tif ( n < 1 ) {\r\n\r\n\t\t\t\t\t\tparams.opacity = n;\r\n\t\t\t\t\t\tparams.transparent = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tcase 'tr':\r\n\t\t\t\t\tn = parseFloat( value );\r\n\r\n\t\t\t\t\tif ( this.options && this.options.invertTrProperty ) n = 1 - n;\r\n\r\n\t\t\t\t\tif ( n > 0 ) {\r\n\r\n\t\t\t\t\t\tparams.opacity = 1 - n;\r\n\t\t\t\t\t\tparams.transparent = true;\r\n\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t\tdefault:\r\n\t\t\t\t\tbreak;\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t\tthis.materials[ materialName ] = new THREE.MeshPhongMaterial( params );\r\n\t\treturn this.materials[ materialName ];\r\n\r\n\t},\r\n\r\n\tgetTextureParams: function ( value, matParams ) {\r\n\r\n\t\tvar texParams = {\r\n\r\n\t\t\tscale: new THREE.Vector2( 1, 1 ),\r\n\t\t\toffset: new THREE.Vector2( 0, 0 )\r\n\r\n\t\t };\r\n\r\n\t\tvar items = value.split( /\\s+/ );\r\n\t\tvar pos;\r\n\r\n\t\tpos = items.indexOf( '-bm' );\r\n\r\n\t\tif ( pos >= 0 ) {\r\n\r\n\t\t\tmatParams.bumpScale = parseFloat( items[ pos + 1 ] );\r\n\t\t\titems.splice( pos, 2 );\r\n\r\n\t\t}\r\n\r\n\t\tpos = items.indexOf( '-s' );\r\n\r\n\t\tif ( pos >= 0 ) {\r\n\r\n\t\t\ttexParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );\r\n\t\t\titems.splice( pos, 4 ); // we expect 3 parameters here!\r\n\r\n\t\t}\r\n\r\n\t\tpos = items.indexOf( '-o' );\r\n\r\n\t\tif ( pos >= 0 ) {\r\n\r\n\t\t\ttexParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );\r\n\t\t\titems.splice( pos, 4 ); // we expect 3 parameters here!\r\n\r\n\t\t}\r\n\r\n\t\ttexParams.url = items.join( ' ' ).trim();\r\n\t\treturn texParams;\r\n\r\n\t},\r\n\r\n\tloadTexture: function ( url, mapping, onLoad, onProgress, onError ) {\r\n\r\n\t\tvar texture;\r\n\t\tvar manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;\r\n\t\tvar loader = manager.getHandler( url );\r\n\r\n\t\tif ( loader === null ) {\r\n\r\n\t\t\tloader = new THREE.TextureLoader( manager );\r\n\r\n\t\t}\r\n\r\n\t\tif ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );\r\n\t\ttexture = loader.load( url, onLoad, onProgress, onError );\r\n\r\n\t\tif ( mapping !== undefined ) texture.mapping = mapping;\r\n\r\n\t\treturn texture;\r\n\r\n\t}\r\n\r\n};\r\n", @@ -293,25 +294,26 @@ "\"use strict\";\nvar window = require(\"global/window\")\nvar isFunction = require(\"is-function\")\nvar parseHeaders = require(\"parse-headers\")\nvar xtend = require(\"xtend\")\n\nmodule.exports = createXHR\n// Allow use of default import syntax in TypeScript\nmodule.exports.default = createXHR;\ncreateXHR.XMLHttpRequest = window.XMLHttpRequest || noop\ncreateXHR.XDomainRequest = \"withCredentials\" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest\n\nforEachArray([\"get\", \"put\", \"post\", \"patch\", \"head\", \"delete\"], function(method) {\n createXHR[method === \"delete\" ? \"del\" : method] = function(uri, options, callback) {\n options = initParams(uri, options, callback)\n options.method = method.toUpperCase()\n return _createXHR(options)\n }\n})\n\nfunction forEachArray(array, iterator) {\n for (var i = 0; i < array.length; i++) {\n iterator(array[i])\n }\n}\n\nfunction isEmpty(obj){\n for(var i in obj){\n if(obj.hasOwnProperty(i)) return false\n }\n return true\n}\n\nfunction initParams(uri, options, callback) {\n var params = uri\n\n if (isFunction(options)) {\n callback = options\n if (typeof uri === \"string\") {\n params = {uri:uri}\n }\n } else {\n params = xtend(options, {uri: uri})\n }\n\n params.callback = callback\n return params\n}\n\nfunction createXHR(uri, options, callback) {\n options = initParams(uri, options, callback)\n return _createXHR(options)\n}\n\nfunction _createXHR(options) {\n if(typeof options.callback === \"undefined\"){\n throw new Error(\"callback argument missing\")\n }\n\n var called = false\n var callback = function cbOnce(err, response, body){\n if(!called){\n called = true\n options.callback(err, response, body)\n }\n }\n\n function readystatechange() {\n if (xhr.readyState === 4) {\n setTimeout(loadFunc, 0)\n }\n }\n\n function getBody() {\n // Chrome with requestType=blob throws errors arround when even testing access to responseText\n var body = undefined\n\n if (xhr.response) {\n body = xhr.response\n } else {\n body = xhr.responseText || getXml(xhr)\n }\n\n if (isJson) {\n try {\n body = JSON.parse(body)\n } catch (e) {}\n }\n\n return body\n }\n\n function errorFunc(evt) {\n clearTimeout(timeoutTimer)\n if(!(evt instanceof Error)){\n evt = new Error(\"\" + (evt || \"Unknown XMLHttpRequest Error\") )\n }\n evt.statusCode = 0\n return callback(evt, failureResponse)\n }\n\n // will load the data & process the response in a special response object\n function loadFunc() {\n if (aborted) return\n var status\n clearTimeout(timeoutTimer)\n if(options.useXDR && xhr.status===undefined) {\n //IE8 CORS GET successful response doesn't have a status field, but body is fine\n status = 200\n } else {\n status = (xhr.status === 1223 ? 204 : xhr.status)\n }\n var response = failureResponse\n var err = null\n\n if (status !== 0){\n response = {\n body: getBody(),\n statusCode: status,\n method: method,\n headers: {},\n url: uri,\n rawRequest: xhr\n }\n if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE\n response.headers = parseHeaders(xhr.getAllResponseHeaders())\n }\n } else {\n err = new Error(\"Internal XMLHttpRequest Error\")\n }\n return callback(err, response, response.body)\n }\n\n var xhr = options.xhr || null\n\n if (!xhr) {\n if (options.cors || options.useXDR) {\n xhr = new createXHR.XDomainRequest()\n }else{\n xhr = new createXHR.XMLHttpRequest()\n }\n }\n\n var key\n var aborted\n var uri = xhr.url = options.uri || options.url\n var method = xhr.method = options.method || \"GET\"\n var body = options.body || options.data\n var headers = xhr.headers = options.headers || {}\n var sync = !!options.sync\n var isJson = false\n var timeoutTimer\n var failureResponse = {\n body: undefined,\n headers: {},\n statusCode: 0,\n method: method,\n url: uri,\n rawRequest: xhr\n }\n\n if (\"json\" in options && options.json !== false) {\n isJson = true\n headers[\"accept\"] || headers[\"Accept\"] || (headers[\"Accept\"] = \"application/json\") //Don't override existing accept header declared by user\n if (method !== \"GET\" && method !== \"HEAD\") {\n headers[\"content-type\"] || headers[\"Content-Type\"] || (headers[\"Content-Type\"] = \"application/json\") //Don't override existing accept header declared by user\n body = JSON.stringify(options.json === true ? body : options.json)\n }\n }\n\n xhr.onreadystatechange = readystatechange\n xhr.onload = loadFunc\n xhr.onerror = errorFunc\n // IE9 must have onprogress be set to a unique function.\n xhr.onprogress = function () {\n // IE must die\n }\n xhr.onabort = function(){\n aborted = true;\n }\n xhr.ontimeout = errorFunc\n xhr.open(method, uri, !sync, options.username, options.password)\n //has to be after open\n if(!sync) {\n xhr.withCredentials = !!options.withCredentials\n }\n // Cannot set timeout with sync request\n // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly\n // both npm's request and jquery 1.x use this kind of timeout, so this is being consistent\n if (!sync && options.timeout > 0 ) {\n timeoutTimer = setTimeout(function(){\n if (aborted) return\n aborted = true//IE9 may still call readystatechange\n xhr.abort(\"timeout\")\n var e = new Error(\"XMLHttpRequest timeout\")\n e.code = \"ETIMEDOUT\"\n errorFunc(e)\n }, options.timeout )\n }\n\n if (xhr.setRequestHeader) {\n for(key in headers){\n if(headers.hasOwnProperty(key)){\n xhr.setRequestHeader(key, headers[key])\n }\n }\n } else if (options.headers && !isEmpty(options.headers)) {\n throw new Error(\"Headers cannot be set on an XDomainRequest object\")\n }\n\n if (\"responseType\" in options) {\n xhr.responseType = options.responseType\n }\n\n if (\"beforeSend\" in options &&\n typeof options.beforeSend === \"function\"\n ) {\n options.beforeSend(xhr)\n }\n\n // Microsoft Edge browser sends \"undefined\" when send is called with undefined value.\n // XMLHttpRequest spec says to pass null as body to indicate no body\n // See https://github.com/naugtur/xhr/issues/100.\n xhr.send(body || null)\n\n return xhr\n\n\n}\n\nfunction getXml(xhr) {\n // xhr.responseXML will throw Exception \"InvalidStateError\" or \"DOMException\"\n // See https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseXML.\n try {\n if (xhr.responseType === \"document\") {\n return xhr.responseXML\n }\n var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === \"parsererror\"\n if (xhr.responseType === \"\" && !firefoxBugTakenEffect) {\n return xhr.responseXML\n }\n } catch (e) {}\n\n return null\n}\n\nfunction noop() {}\n", "module.exports = (function xmlparser() {\n //common browsers\n if (typeof self.DOMParser !== 'undefined') {\n return function(str) {\n var parser = new self.DOMParser()\n return parser.parseFromString(str, 'application/xml')\n }\n } \n\n //IE8 fallback\n if (typeof self.ActiveXObject !== 'undefined'\n && new self.ActiveXObject('Microsoft.XMLDOM')) {\n return function(str) {\n var xmlDoc = new self.ActiveXObject(\"Microsoft.XMLDOM\")\n xmlDoc.async = \"false\"\n xmlDoc.loadXML(str)\n return xmlDoc\n }\n }\n\n //last resort fallback\n return function(str) {\n var div = document.createElement('div')\n div.innerHTML = str\n return div\n }\n})()\n", "module.exports = extend\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nfunction extend() {\n var target = {}\n\n for (var i = 0; i < arguments.length; i++) {\n var source = arguments[i]\n\n for (var key in source) {\n if (hasOwnProperty.call(source, key)) {\n target[key] = source[key]\n }\n }\n }\n\n return target\n}\n", - "module.exports={\n \"name\": \"aframe\",\n \"version\": \"1.0.3\",\n \"description\": \"A web framework for building virtual reality experiences.\",\n \"homepage\": \"https://aframe.io/\",\n \"main\": \"dist/aframe-master.js\",\n \"scripts\": {\n \"browserify\": \"browserify src/index.js -s 'AFRAME' -p browserify-derequire\",\n \"build\": \"shx mkdir -p build/ && npm run browserify -- --debug -t [envify --INSPECTOR_VERSION dev] -o build/aframe.js\",\n \"codecov\": \"codecov\",\n \"dev\": \"npm run build && cross-env INSPECTOR_VERSION=dev node ./scripts/budo -t envify\",\n \"dist\": \"node scripts/updateVersionLog.js && npm run dist:min && npm run dist:max\",\n \"dist:max\": \"npm run browserify -s -- --debug | exorcist dist/aframe-master.js.map > dist/aframe-master.js\",\n \"dist:min\": \"npm run browserify -s -- --debug -p [minifyify --map aframe-master.min.js.map --output dist/aframe-master.min.js.map] -o dist/aframe-master.min.js\",\n \"docs\": \"markserv --dir docs --port 9001\",\n \"preghpages\": \"node ./scripts/preghpages.js\",\n \"ghpages\": \"ghpages -p gh-pages/\",\n \"lint\": \"semistandard -v | snazzy\",\n \"lint:fix\": \"semistandard --fix\",\n \"precommit\": \"npm run lint\",\n \"prepush\": \"node scripts/testOnlyCheck.js\",\n \"prerelease\": \"cross-env node scripts/release.js 1.0.2 1.0.3\",\n \"start\": \"npm run dev\",\n \"start:https\": \"cross-env SSL=true npm run dev\",\n \"test\": \"karma start ./tests/karma.conf.js\",\n \"test:docs\": \"node scripts/docsLint.js\",\n \"test:firefox\": \"npm test -- --browsers Firefox\",\n \"test:chrome\": \"npm test -- --browsers Chrome\",\n \"test:nobrowser\": \"NO_BROWSER=true npm test\",\n \"test:node\": \"mocha --ui tdd tests/node\"\n },\n \"repository\": \"aframevr/aframe\",\n \"license\": \"MIT\",\n \"files\": [\n \"dist/*\",\n \"docs/**/*\",\n \"src/**/*\",\n \"vendor/**/*\"\n ],\n \"dependencies\": {\n \"custom-event-polyfill\": \"^1.0.6\",\n \"debug\": \"ngokevin/debug#noTimestamp\",\n \"deep-assign\": \"^2.0.0\",\n \"document-register-element\": \"dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90\",\n \"load-bmfont\": \"^1.2.3\",\n \"object-assign\": \"^4.0.1\",\n \"present\": \"0.0.6\",\n \"promise-polyfill\": \"^3.1.0\",\n \"super-animejs\": \"^3.1.0\",\n \"super-three\": \"^0.111.5\",\n \"three-bmfont-text\": \"dmarcos/three-bmfont-text#1babdf8507\",\n \"webvr-polyfill\": \"^0.10.10\"\n },\n \"devDependencies\": {\n \"browserify\": \"^13.1.0\",\n \"browserify-css\": \"^0.8.4\",\n \"browserify-derequire\": \"^0.9.4\",\n \"browserify-istanbul\": \"^2.0.0\",\n \"budo\": \"^9.2.0\",\n \"chai\": \"^3.5.0\",\n \"chai-shallow-deep-equal\": \"^1.4.0\",\n \"chalk\": \"^1.1.3\",\n \"codecov\": \"^1.0.1\",\n \"cross-env\": \"^5.0.1\",\n \"envify\": \"^3.4.1\",\n \"exorcist\": \"^0.4.0\",\n \"ghpages\": \"0.0.8\",\n \"git-rev\": \"^0.2.1\",\n \"glob\": \"^7.1.1\",\n \"husky\": \"^0.11.7\",\n \"istanbul\": \"^0.4.5\",\n \"jsdom\": \"^9.11.0\",\n \"karma\": \"1.4.1\",\n \"karma-browserify\": \"^5.1.0\",\n \"karma-chai-shallow-deep-equal\": \"0.0.4\",\n \"karma-chrome-launcher\": \"^2.0.0\",\n \"karma-coverage\": \"^1.1.1\",\n \"karma-env-preprocessor\": \"^0.1.1\",\n \"karma-firefox-launcher\": \"^1.2.0\",\n \"karma-mocha\": \"^1.1.1\",\n \"karma-mocha-reporter\": \"^2.1.0\",\n \"karma-sinon-chai\": \"1.2.4\",\n \"lolex\": \"^1.5.1\",\n \"markserv\": \"github:sukima/markserv#feature/fix-broken-websoketio-link\",\n \"minifyify\": \"^7.3.3\",\n \"mocha\": \"^3.0.2\",\n \"mozilla-download\": \"^1.1.1\",\n \"replace-in-file\": \"^2.5.3\",\n \"semistandard\": \"^9.0.0\",\n \"shelljs\": \"^0.7.7\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^1.17.5\",\n \"sinon-chai\": \"2.8.0\",\n \"snazzy\": \"^5.0.0\",\n \"too-wordy\": \"ngokevin/too-wordy\",\n \"uglifyjs\": \"^2.4.10\",\n \"write-good\": \"^0.9.1\"\n },\n \"link\": true,\n \"browserify\": {\n \"transform\": [\n \"browserify-css\",\n \"envify\"\n ]\n },\n \"semistandard\": {\n \"ignore\": [\n \"build/**\",\n \"dist/**\",\n \"examples/**/shaders/*.js\",\n \"**/vendor/**\"\n ]\n },\n \"keywords\": [\n \"3d\",\n \"aframe\",\n \"cardboard\",\n \"components\",\n \"oculus\",\n \"three\",\n \"three.js\",\n \"rift\",\n \"vive\",\n \"vr\",\n \"web-components\",\n \"webvr\"\n ],\n \"browserify-css\": {\n \"minify\": true\n },\n \"engines\": {\n \"node\": \">= 4.6.0\",\n \"npm\": \"^2.15.9\"\n }\n}\n", + "module.exports={\n \"name\": \"aframe\",\n \"version\": \"1.0.4\",\n \"description\": \"A web framework for building virtual reality experiences.\",\n \"homepage\": \"https://aframe.io/\",\n \"main\": \"dist/aframe-master.js\",\n \"scripts\": {\n \"browserify\": \"browserify src/index.js -s 'AFRAME' -p browserify-derequire\",\n \"build\": \"shx mkdir -p build/ && npm run browserify -- --debug -t [ envify --INSPECTOR_VERSION dev ] -o build/aframe.js\",\n \"codecov\": \"codecov\",\n \"dev\": \"npm run build && cross-env INSPECTOR_VERSION=dev node ./scripts/budo -t envify\",\n \"dist\": \"node scripts/updateVersionLog.js && npm run dist:min && npm run dist:max\",\n \"dist:max\": \"npm run browserify -s -- --debug | exorcist dist/aframe-master.js.map > dist/aframe-master.js\",\n \"dist:min\": \"npm run browserify -s -- --debug -p [ minifyify --map aframe-master.min.js.map --output dist/aframe-master.min.js.map ] -o dist/aframe-master.min.js\",\n \"docs\": \"markserv --dir docs --port 9001\",\n \"preghpages\": \"node ./scripts/preghpages.js\",\n \"ghpages\": \"ghpages -p gh-pages/\",\n \"lint\": \"semistandard -v | snazzy\",\n \"lint:fix\": \"semistandard --fix\",\n \"precommit\": \"npm run lint\",\n \"prepush\": \"node scripts/testOnlyCheck.js\",\n \"prerelease\": \"node scripts/release.js 1.0.3 1.0.4\",\n \"start\": \"npm run dev\",\n \"start:https\": \"cross-env SSL=true npm run dev\",\n \"test\": \"karma start ./tests/karma.conf.js\",\n \"test:docs\": \"node scripts/docsLint.js\",\n \"test:firefox\": \"npm test -- --browsers Firefox\",\n \"test:chrome\": \"npm test -- --browsers Chrome\",\n \"test:nobrowser\": \"NO_BROWSER=true npm test\",\n \"test:node\": \"mocha --ui tdd tests/node\"\n },\n \"repository\": \"aframevr/aframe\",\n \"license\": \"MIT\",\n \"files\": [\n \"dist/*\",\n \"docs/**/*\",\n \"src/**/*\",\n \"vendor/**/*\"\n ],\n \"dependencies\": {\n \"custom-event-polyfill\": \"^1.0.6\",\n \"debug\": \"ngokevin/debug#noTimestamp\",\n \"deep-assign\": \"^2.0.0\",\n \"document-register-element\": \"dmarcos/document-register-element#8ccc532b7f3744be954574caf3072a5fd260ca90\",\n \"load-bmfont\": \"^1.2.3\",\n \"object-assign\": \"^4.0.1\",\n \"present\": \"0.0.6\",\n \"promise-polyfill\": \"^3.1.0\",\n \"super-animejs\": \"^3.1.0\",\n \"super-three\": \"^0.111.6\",\n \"three-bmfont-text\": \"dmarcos/three-bmfont-text#1babdf8507c731a18f8af3b807292e2b9740955e\",\n \"webvr-polyfill\": \"^0.10.10\"\n },\n \"devDependencies\": {\n \"browserify\": \"^13.1.0\",\n \"browserify-css\": \"^0.8.4\",\n \"browserify-derequire\": \"^0.9.4\",\n \"browserify-istanbul\": \"^2.0.0\",\n \"budo\": \"^9.2.0\",\n \"chai\": \"^3.5.0\",\n \"chai-shallow-deep-equal\": \"^1.4.0\",\n \"chalk\": \"^1.1.3\",\n \"codecov\": \"^1.0.1\",\n \"cross-env\": \"^5.0.1\",\n \"envify\": \"^3.4.1\",\n \"exorcist\": \"^0.4.0\",\n \"ghpages\": \"0.0.8\",\n \"git-rev\": \"^0.2.1\",\n \"glob\": \"^7.1.1\",\n \"husky\": \"^0.11.7\",\n \"istanbul\": \"^0.4.5\",\n \"jsdom\": \"^9.11.0\",\n \"karma\": \"1.4.1\",\n \"karma-browserify\": \"^5.1.0\",\n \"karma-chai-shallow-deep-equal\": \"0.0.4\",\n \"karma-chrome-launcher\": \"^2.0.0\",\n \"karma-coverage\": \"^1.1.1\",\n \"karma-env-preprocessor\": \"^0.1.1\",\n \"karma-firefox-launcher\": \"^1.2.0\",\n \"karma-mocha\": \"^1.1.1\",\n \"karma-mocha-reporter\": \"^2.1.0\",\n \"karma-sinon-chai\": \"1.2.4\",\n \"lolex\": \"^1.5.1\",\n \"markserv\": \"github:sukima/markserv#feature/fix-broken-websoketio-link\",\n \"minifyify\": \"^7.3.3\",\n \"mocha\": \"^3.0.2\",\n \"mozilla-download\": \"^1.1.1\",\n \"replace-in-file\": \"^2.5.3\",\n \"semistandard\": \"^9.0.0\",\n \"shelljs\": \"^0.7.7\",\n \"shx\": \"^0.2.2\",\n \"sinon\": \"^1.17.5\",\n \"sinon-chai\": \"2.8.0\",\n \"snazzy\": \"^5.0.0\",\n \"too-wordy\": \"ngokevin/too-wordy\",\n \"uglifyjs\": \"^2.4.10\",\n \"write-good\": \"^0.9.1\"\n },\n \"link\": true,\n \"browserify\": {\n \"transform\": [\n \"browserify-css\",\n \"envify\"\n ]\n },\n \"semistandard\": {\n \"ignore\": [\n \"build/**\",\n \"dist/**\",\n \"examples/**/shaders/*.js\",\n \"**/vendor/**\"\n ]\n },\n \"keywords\": [\n \"3d\",\n \"aframe\",\n \"cardboard\",\n \"components\",\n \"oculus\",\n \"three\",\n \"three.js\",\n \"rift\",\n \"vive\",\n \"vr\",\n \"web-components\",\n \"webvr\"\n ],\n \"browserify-css\": {\n \"minify\": true\n },\n \"engines\": {\n \"node\": \">= 4.6.0\",\n \"npm\": \"^2.15.9\"\n }\n}\n", "var anime = require('super-animejs');\nvar components = require('../core/component').components;\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils');\n\nvar colorHelperFrom = new THREE.Color();\nvar colorHelperTo = new THREE.Color();\n\nvar getComponentProperty = utils.entity.getComponentProperty;\nvar setComponentProperty = utils.entity.setComponentProperty;\nvar splitCache = {};\n\nvar TYPE_COLOR = 'color';\nvar PROP_POSITION = 'position';\nvar PROP_ROTATION = 'rotation';\nvar PROP_SCALE = 'scale';\nvar STRING_COMPONENTS = 'components';\nvar STRING_OBJECT3D = 'object3D';\n\n/**\n * Animation component for A-Frame using anime.js.\n *\n * The component manually controls the tick by setting `autoplay: false` on anime.js and\n * manually * calling `animation.tick()` in the tick handler. To pause or resume, we toggle a\n * boolean * flag * `isAnimationPlaying`.\n *\n * anime.js animation config for tweenining Javascript objects and values works as:\n *\n * config = {\n * targets: {foo: 0.0, bar: '#000'},\n * foo: 1.0,\n * bar: '#FFF'\n * }\n *\n * The above will tween each property in `targets`. The `to` values are set in the root of\n * the config.\n *\n * @member {object} animation - anime.js instance.\n * @member {boolean} animationIsPlaying - Control if animation is playing.\n */\nmodule.exports.Component = registerComponent('animation', {\n schema: {\n autoplay: {default: true},\n delay: {default: 0},\n dir: {default: ''},\n dur: {default: 1000},\n easing: {default: 'easeInQuad'},\n elasticity: {default: 400},\n enabled: {default: true},\n from: {default: ''},\n loop: {\n default: 0,\n parse: function (value) {\n // Boolean or integer.\n if (value === true || value === 'true') { return true; }\n if (value === false || value === 'false') { return false; }\n return parseInt(value, 10);\n }\n },\n property: {default: ''},\n startEvents: {type: 'array'},\n pauseEvents: {type: 'array'},\n resumeEvents: {type: 'array'},\n round: {default: false},\n to: {default: ''},\n type: {default: ''},\n isRawProperty: {default: false}\n },\n\n multiple: true,\n\n init: function () {\n var self = this;\n\n this.eventDetail = {name: this.attrName};\n this.time = 0;\n\n this.animation = null;\n this.animationIsPlaying = false;\n this.onStartEvent = this.onStartEvent.bind(this);\n this.beginAnimation = this.beginAnimation.bind(this);\n this.pauseAnimation = this.pauseAnimation.bind(this);\n this.resumeAnimation = this.resumeAnimation.bind(this);\n\n this.fromColor = {};\n this.toColor = {};\n this.targets = {};\n this.targetsArray = [];\n\n this.updateConfigForDefault = this.updateConfigForDefault.bind(this);\n this.updateConfigForRawColor = this.updateConfigForRawColor.bind(this);\n\n this.config = {\n complete: function () {\n self.animationIsPlaying = false;\n self.el.emit('animationcomplete', self.eventDetail, false);\n if (self.id) {\n self.el.emit('animationcomplete__' + self.id, self.eventDetail, false);\n }\n }\n };\n },\n\n update: function (oldData) {\n var config = this.config;\n var data = this.data;\n\n this.animationIsPlaying = false;\n\n if (!this.data.enabled) { return; }\n\n if (!data.property) { return; }\n\n // Base config.\n config.autoplay = false;\n config.direction = data.dir;\n config.duration = data.dur;\n config.easing = data.easing;\n config.elasticity = data.elasticity;\n config.loop = data.loop;\n config.round = data.round;\n\n // Start new animation.\n this.createAndStartAnimation();\n },\n\n tick: function (t, dt) {\n if (!this.animationIsPlaying) { return; }\n this.time += dt;\n this.animation.tick(this.time);\n },\n\n remove: function () {\n this.pauseAnimation();\n this.removeEventListeners();\n },\n\n pause: function () {\n this.paused = true;\n this.pausedWasPlaying = this.animationIsPlaying;\n this.pauseAnimation();\n this.removeEventListeners();\n },\n\n /**\n * `play` handler only for resuming scene.\n */\n play: function () {\n if (!this.paused) { return; }\n this.paused = false;\n this.addEventListeners();\n if (this.pausedWasPlaying) {\n this.resumeAnimation();\n this.pausedWasPlaying = false;\n }\n },\n\n /**\n * Start animation from scratch.\n */\n createAndStartAnimation: function () {\n var data = this.data;\n\n this.updateConfig();\n this.animationIsPlaying = false;\n this.animation = anime(this.config);\n this.animation.began = true;\n\n this.removeEventListeners();\n this.addEventListeners();\n\n // Wait for start events for animation.\n if (!data.autoplay || data.startEvents && data.startEvents.length) { return; }\n\n // Delay animation.\n if (data.delay) {\n setTimeout(this.beginAnimation, data.delay);\n return;\n }\n\n // Play animation.\n this.beginAnimation();\n },\n\n /**\n * This is before animation start (including from startEvents).\n * Set to initial state (config.from, time = 0, seekTime = 0).\n */\n beginAnimation: function () {\n this.updateConfig();\n this.animation.began = true;\n this.time = 0;\n this.animationIsPlaying = true;\n this.stopRelatedAnimations();\n this.el.emit('animationbegin', this.eventDetail, false);\n },\n\n pauseAnimation: function () {\n this.animationIsPlaying = false;\n },\n\n resumeAnimation: function () {\n this.animationIsPlaying = true;\n },\n\n /**\n * startEvents callback.\n */\n onStartEvent: function () {\n if (!this.data.enabled) { return; }\n\n this.updateConfig();\n if (this.animation) {\n this.animation.pause();\n }\n this.animation = anime(this.config);\n\n // Include the delay before each start event.\n if (this.data.delay) {\n setTimeout(this.beginAnimation, this.data.delay);\n return;\n }\n this.beginAnimation();\n },\n\n /**\n * rawProperty: true and type: color;\n */\n updateConfigForRawColor: function () {\n var config = this.config;\n var data = this.data;\n var el = this.el;\n var from;\n var key;\n var to;\n\n if (this.waitComponentInitRawProperty(this.updateConfigForRawColor)) {\n return;\n }\n\n from = data.from === '' ? getRawProperty(el, data.property) : data.from;\n to = data.to;\n\n // Use r/g/b vector for color type.\n this.setColorConfig(from, to);\n from = this.fromColor;\n to = this.toColor;\n\n this.targetsArray.length = 0;\n this.targetsArray.push(from);\n config.targets = this.targetsArray;\n for (key in to) { config[key] = to[key]; }\n\n config.update = (function () {\n var lastValue = {};\n return function (anim) {\n var value;\n value = anim.animatables[0].target;\n // For animation timeline.\n if (value.r === lastValue.r &&\n value.g === lastValue.g &&\n value.b === lastValue.b) { return; }\n\n setRawProperty(el, data.property, value, data.type);\n };\n })();\n },\n\n /**\n * Stuff property into generic `property` key.\n */\n updateConfigForDefault: function () {\n var config = this.config;\n var data = this.data;\n var el = this.el;\n var from;\n var isBoolean;\n var isNumber;\n var to;\n\n if (this.waitComponentInitRawProperty(this.updateConfigForDefault)) {\n return;\n }\n\n if (data.from === '') {\n // Infer from.\n from = isRawProperty(data)\n ? getRawProperty(el, data.property)\n : getComponentProperty(el, data.property);\n } else {\n // Explicit from.\n from = data.from;\n }\n\n to = data.to;\n\n isNumber = !isNaN(from || to);\n if (isNumber) {\n from = parseFloat(from);\n to = parseFloat(to);\n } else {\n from = from ? from.toString() : from;\n to = to ? to.toString() : to;\n }\n\n // Convert booleans to integer to allow boolean flipping.\n isBoolean = data.to === 'true' || data.to === 'false' ||\n data.to === true || data.to === false;\n if (isBoolean) {\n from = data.from === 'true' || data.from === true ? 1 : 0;\n to = data.to === 'true' || data.to === true ? 1 : 0;\n }\n\n this.targets.aframeProperty = from;\n config.targets = this.targets;\n config.aframeProperty = to;\n config.update = (function () {\n var lastValue;\n\n return function (anim) {\n var value;\n value = anim.animatables[0].target.aframeProperty;\n\n // Need to do a last value check for animation timeline since all the tweening\n // begins simultaenously even if the value has not changed. Also better for perf\n // anyways.\n if (value === lastValue) { return; }\n lastValue = value;\n\n if (isBoolean) { value = value >= 1; }\n\n if (isRawProperty(data)) {\n setRawProperty(el, data.property, value, data.type);\n } else {\n setComponentProperty(el, data.property, value);\n }\n };\n })();\n },\n\n /**\n * Extend x/y/z/w onto the config.\n * Update vector by modifying object3D.\n */\n updateConfigForVector: function () {\n var config = this.config;\n var data = this.data;\n var el = this.el;\n var key;\n var from;\n var to;\n\n // Parse coordinates.\n from = data.from !== ''\n ? utils.coordinates.parse(data.from) // If data.from defined, use that.\n : getComponentProperty(el, data.property); // If data.from not defined, get on the fly.\n to = utils.coordinates.parse(data.to);\n\n if (data.property === PROP_ROTATION) {\n toRadians(from);\n toRadians(to);\n }\n\n // Set to and from.\n this.targetsArray.length = 0;\n this.targetsArray.push(from);\n config.targets = this.targetsArray;\n for (key in to) { config[key] = to[key]; }\n\n // If animating object3D transformation, run more optimized updater.\n if (data.property === PROP_POSITION || data.property === PROP_ROTATION ||\n data.property === PROP_SCALE) {\n config.update = (function () {\n var lastValue = {};\n return function (anim) {\n var value = anim.animatables[0].target;\n\n if (data.property === PROP_SCALE) {\n value.x = Math.max(0.0001, value.x);\n value.y = Math.max(0.0001, value.y);\n value.z = Math.max(0.0001, value.z);\n }\n\n // For animation timeline.\n if (value.x === lastValue.x &&\n value.y === lastValue.y &&\n value.z === lastValue.z) { return; }\n\n lastValue.x = value.x;\n lastValue.y = value.y;\n lastValue.z = value.z;\n\n el.object3D[data.property].set(value.x, value.y, value.z);\n };\n })();\n return;\n }\n\n // Animating some vector.\n config.update = (function () {\n var lastValue = {};\n return function (anim) {\n var value = anim.animatables[0].target;\n\n // Animate rotation through radians.\n // For animation timeline.\n if (value.x === lastValue.x &&\n value.y === lastValue.y &&\n value.z === lastValue.z) { return; }\n lastValue.x = value.x;\n lastValue.y = value.y;\n lastValue.z = value.z;\n setComponentProperty(el, data.property, value);\n };\n })();\n },\n\n /**\n * Update the config before each run.\n */\n updateConfig: function () {\n var propType;\n\n // Route config type.\n propType = getPropertyType(this.el, this.data.property);\n if (isRawProperty(this.data) && this.data.type === TYPE_COLOR) {\n this.updateConfigForRawColor();\n } else if (propType === 'vec2' || propType === 'vec3' || propType === 'vec4') {\n this.updateConfigForVector();\n } else {\n this.updateConfigForDefault();\n }\n },\n\n /**\n * Wait for component to initialize.\n */\n waitComponentInitRawProperty: function (cb) {\n var componentName;\n var data = this.data;\n var el = this.el;\n var self = this;\n\n if (data.from !== '') { return false; }\n\n if (!data.property.startsWith(STRING_COMPONENTS)) { return false; }\n\n componentName = splitDot(data.property)[1];\n if (el.components[componentName]) { return false; }\n\n el.addEventListener('componentinitialized', function wait (evt) {\n if (evt.detail.name !== componentName) { return; }\n cb();\n // Since the config was created async, create the animation now since we missed it\n // earlier.\n self.animation = anime(self.config);\n el.removeEventListener('componentinitialized', wait);\n });\n return true;\n },\n\n /**\n * Make sure two animations on the same property don't fight each other.\n * e.g., animation__mouseenter=\"property: material.opacity\"\n * animation__mouseleave=\"property: material.opacity\"\n */\n stopRelatedAnimations: function () {\n var component;\n var componentName;\n for (componentName in this.el.components) {\n component = this.el.components[componentName];\n if (componentName === this.attrName) { continue; }\n if (component.name !== 'animation') { continue; }\n if (!component.animationIsPlaying) { continue; }\n if (component.data.property !== this.data.property) { continue; }\n component.animationIsPlaying = false;\n }\n },\n\n addEventListeners: function () {\n var data = this.data;\n var el = this.el;\n addEventListeners(el, data.startEvents, this.onStartEvent);\n addEventListeners(el, data.pauseEvents, this.pauseAnimation);\n addEventListeners(el, data.resumeEvents, this.resumeAnimation);\n },\n\n removeEventListeners: function () {\n var data = this.data;\n var el = this.el;\n removeEventListeners(el, data.startEvents, this.onStartEvent);\n removeEventListeners(el, data.pauseEvents, this.pauseAnimation);\n removeEventListeners(el, data.resumeEvents, this.resumeAnimation);\n },\n\n setColorConfig: function (from, to) {\n colorHelperFrom.set(from);\n colorHelperTo.set(to);\n from = this.fromColor;\n to = this.toColor;\n from.r = colorHelperFrom.r;\n from.g = colorHelperFrom.g;\n from.b = colorHelperFrom.b;\n to.r = colorHelperTo.r;\n to.g = colorHelperTo.g;\n to.b = colorHelperTo.b;\n }\n});\n\n/**\n * Given property name, check schema to see what type we are animating.\n * We just care whether the property is a vector.\n */\nfunction getPropertyType (el, property) {\n var component;\n var componentName;\n var split;\n var propertyName;\n\n split = property.split('.');\n componentName = split[0];\n propertyName = split[1];\n component = el.components[componentName] || components[componentName];\n\n // Primitives.\n if (!component) { return null; }\n\n // Dynamic schema. We only care about vectors anyways.\n if (propertyName && !component.schema[propertyName]) { return null; }\n\n // Multi-prop.\n if (propertyName) { return component.schema[propertyName].type; }\n\n // Single-prop.\n return component.schema.type;\n}\n\n/**\n * Convert object to radians.\n */\nfunction toRadians (obj) {\n obj.x = THREE.Math.degToRad(obj.x);\n obj.y = THREE.Math.degToRad(obj.y);\n obj.z = THREE.Math.degToRad(obj.z);\n}\n\nfunction addEventListeners (el, eventNames, handler) {\n var i;\n for (i = 0; i < eventNames.length; i++) {\n el.addEventListener(eventNames[i], handler);\n }\n}\n\nfunction removeEventListeners (el, eventNames, handler) {\n var i;\n for (i = 0; i < eventNames.length; i++) {\n el.removeEventListener(eventNames[i], handler);\n }\n}\n\nfunction getRawProperty (el, path) {\n var i;\n var split;\n var value;\n split = splitDot(path);\n value = el;\n for (i = 0; i < split.length; i++) {\n value = value[split[i]];\n }\n if (value === undefined) {\n console.log(el);\n throw new Error('[animation] property (' + path + ') could not be found');\n }\n return value;\n}\n\nfunction setRawProperty (el, path, value, type) {\n var i;\n var split;\n var propertyName;\n var targetValue;\n\n if (path.startsWith('object3D.rotation')) {\n value = THREE.Math.degToRad(value);\n }\n\n // Walk.\n split = splitDot(path);\n targetValue = el;\n for (i = 0; i < split.length - 1; i++) { targetValue = targetValue[split[i]]; }\n propertyName = split[split.length - 1];\n\n // Raw color.\n if (type === TYPE_COLOR) {\n if ('r' in targetValue[propertyName]) {\n targetValue[propertyName].r = value.r;\n targetValue[propertyName].g = value.g;\n targetValue[propertyName].b = value.b;\n } else {\n targetValue[propertyName].x = value.r;\n targetValue[propertyName].y = value.g;\n targetValue[propertyName].z = value.b;\n }\n return;\n }\n\n targetValue[propertyName] = value;\n}\n\nfunction splitDot (path) {\n if (path in splitCache) { return splitCache[path]; }\n splitCache[path] = path.split('.');\n return splitCache[path];\n}\n\nfunction isRawProperty (data) {\n return data.isRawProperty || data.property.startsWith(STRING_COMPONENTS) ||\n data.property.startsWith(STRING_OBJECT3D);\n}\n", "var registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\n\n/**\n * Camera component.\n * Pairs along with camera system to handle tracking the active camera.\n */\nmodule.exports.Component = registerComponent('camera', {\n schema: {\n active: {default: true},\n far: {default: 10000},\n fov: {default: 80, min: 0},\n near: {default: 0.005, min: 0},\n spectator: {default: false},\n zoom: {default: 1, min: 0}\n },\n\n /**\n * Initialize three.js camera and add it to the entity.\n * Add reference from scene to this entity as the camera.\n */\n init: function () {\n var camera;\n var el = this.el;\n\n // Create camera.\n camera = this.camera = new THREE.PerspectiveCamera();\n el.setObject3D('camera', camera);\n },\n\n /**\n * Update three.js camera.\n */\n update: function (oldData) {\n var data = this.data;\n var camera = this.camera;\n\n // Update properties.\n camera.aspect = data.aspect || (window.innerWidth / window.innerHeight);\n camera.far = data.far;\n camera.fov = data.fov;\n camera.near = data.near;\n camera.zoom = data.zoom;\n camera.updateProjectionMatrix();\n\n this.updateActiveCamera(oldData);\n this.updateSpectatorCamera(oldData);\n },\n\n updateActiveCamera: function (oldData) {\n var data = this.data;\n var el = this.el;\n var system = this.system;\n // Active property did not change.\n if (oldData && oldData.active === data.active || data.spectator) { return; }\n\n // If `active` property changes, or first update, handle active camera with system.\n if (data.active && system.activeCameraEl !== el) {\n // Camera enabled. Set camera to this camera.\n system.setActiveCamera(el);\n } else if (!data.active && system.activeCameraEl === el) {\n // Camera disabled. Set camera to another camera.\n system.disableActiveCamera();\n }\n },\n\n updateSpectatorCamera: function (oldData) {\n var data = this.data;\n var el = this.el;\n var system = this.system;\n // spectator property did not change.\n if (oldData && oldData.spectator === data.spectator) { return; }\n\n // If `spectator` property changes, or first update, handle spectator camera with system.\n if (data.spectator && system.spectatorCameraEl !== el) {\n // Camera enabled. Set camera to this camera.\n system.setSpectatorCamera(el);\n } else if (!data.spectator && system.spectatorCameraEl === el) {\n // Camera disabled. Set camera to another camera.\n system.disableSpectatorCamera();\n }\n },\n\n /**\n * Remove camera on remove (callback).\n */\n remove: function () {\n this.el.removeObject3D('camera');\n }\n});\n", - "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\nvar utils = require('../utils/');\n\nvar bind = utils.bind;\n\nvar EVENTS = {\n CLICK: 'click',\n FUSING: 'fusing',\n MOUSEENTER: 'mouseenter',\n MOUSEDOWN: 'mousedown',\n MOUSELEAVE: 'mouseleave',\n MOUSEUP: 'mouseup'\n};\n\nvar STATES = {\n FUSING: 'cursor-fusing',\n HOVERING: 'cursor-hovering',\n HOVERED: 'cursor-hovered'\n};\n\nvar CANVAS_EVENTS = {\n DOWN: ['mousedown', 'touchstart'],\n UP: ['mouseup', 'touchend']\n};\n\nvar CANVAS_HOVER_CLASS = 'a-mouse-cursor-hover';\n\n/**\n * Cursor component. Applies the raycaster component specifically for starting the raycaster\n * from the camera and pointing from camera's facing direction, and then only returning the\n * closest intersection. Cursor can be fine-tuned by setting raycaster properties.\n *\n * @member {object} fuseTimeout - Timeout to trigger fuse-click.\n * @member {Element} cursorDownEl - Entity that was last mousedowned during current click.\n * @member {object} intersection - Attributes of the current intersection event, including\n * 3D- and 2D-space coordinates. See: http://threejs.org/docs/api/core/Raycaster.html\n * @member {Element} intersectedEl - Currently-intersected entity. Used to keep track to\n * emit events when unintersecting.\n */\nmodule.exports.Component = registerComponent('cursor', {\n dependencies: ['raycaster'],\n\n schema: {\n downEvents: {default: []},\n fuse: {default: utils.device.isMobile()},\n fuseTimeout: {default: 1500, min: 0},\n mouseCursorStylesEnabled: {default: true},\n upEvents: {default: []},\n rayOrigin: {default: 'entity', oneOf: ['mouse', 'entity']}\n },\n\n init: function () {\n var self = this;\n\n this.fuseTimeout = undefined;\n this.cursorDownEl = null;\n this.intersectedEl = null;\n this.canvasBounds = document.body.getBoundingClientRect();\n this.isCursorDown = false;\n\n // Debounce.\n this.updateCanvasBounds = utils.debounce(function updateCanvasBounds () {\n self.canvasBounds = self.el.sceneEl.canvas.getBoundingClientRect();\n }, 500);\n\n this.eventDetail = {};\n this.intersectedEventDetail = {cursorEl: this.el};\n\n // Bind methods.\n this.onCursorDown = bind(this.onCursorDown, this);\n this.onCursorUp = bind(this.onCursorUp, this);\n this.onIntersection = bind(this.onIntersection, this);\n this.onIntersectionCleared = bind(this.onIntersectionCleared, this);\n this.onMouseMove = bind(this.onMouseMove, this);\n },\n\n update: function (oldData) {\n if (this.data.rayOrigin === oldData.rayOrigin) { return; }\n this.updateMouseEventListeners();\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n },\n\n remove: function () {\n var el = this.el;\n el.removeState(STATES.HOVERING);\n el.removeState(STATES.FUSING);\n clearTimeout(this.fuseTimeout);\n if (this.intersectedEl) { this.intersectedEl.removeState(STATES.HOVERED); }\n this.removeEventListeners();\n },\n\n addEventListeners: function () {\n var canvas;\n var data = this.data;\n var el = this.el;\n var self = this;\n\n function addCanvasListeners () {\n canvas = el.sceneEl.canvas;\n if (data.downEvents.length || data.upEvents.length) { return; }\n CANVAS_EVENTS.DOWN.forEach(function (downEvent) {\n canvas.addEventListener(downEvent, self.onCursorDown);\n });\n CANVAS_EVENTS.UP.forEach(function (upEvent) {\n canvas.addEventListener(upEvent, self.onCursorUp);\n });\n }\n\n canvas = el.sceneEl.canvas;\n if (canvas) {\n addCanvasListeners();\n } else {\n el.sceneEl.addEventListener('render-target-loaded', addCanvasListeners);\n }\n\n data.downEvents.forEach(function (downEvent) {\n el.addEventListener(downEvent, self.onCursorDown);\n });\n data.upEvents.forEach(function (upEvent) {\n el.addEventListener(upEvent, self.onCursorUp);\n });\n el.addEventListener('raycaster-intersection', this.onIntersection);\n el.addEventListener('raycaster-intersection-cleared', this.onIntersectionCleared);\n\n el.sceneEl.addEventListener('rendererresize', this.updateCanvasBounds);\n window.addEventListener('resize', this.updateCanvasBounds);\n window.addEventListener('scroll', this.updateCanvasBounds);\n\n this.updateMouseEventListeners();\n },\n\n removeEventListeners: function () {\n var canvas;\n var data = this.data;\n var el = this.el;\n var self = this;\n\n canvas = el.sceneEl.canvas;\n if (canvas && !data.downEvents.length && !data.upEvents.length) {\n CANVAS_EVENTS.DOWN.forEach(function (downEvent) {\n canvas.removeEventListener(downEvent, self.onCursorDown);\n });\n CANVAS_EVENTS.UP.forEach(function (upEvent) {\n canvas.removeEventListener(upEvent, self.onCursorUp);\n });\n }\n\n data.downEvents.forEach(function (downEvent) {\n el.removeEventListener(downEvent, self.onCursorDown);\n });\n data.upEvents.forEach(function (upEvent) {\n el.removeEventListener(upEvent, self.onCursorUp);\n });\n el.removeEventListener('raycaster-intersection', this.onIntersection);\n el.removeEventListener('raycaster-intersection-cleared', this.onIntersectionCleared);\n canvas.removeEventListener('mousemove', this.onMouseMove);\n canvas.removeEventListener('touchstart', this.onMouseMove);\n canvas.removeEventListener('touchmove', this.onMouseMove);\n\n el.sceneEl.removeEventListener('rendererresize', this.updateCanvasBounds);\n window.removeEventListener('resize', this.updateCanvasBounds);\n window.removeEventListener('scroll', this.updateCanvasBounds);\n },\n\n updateMouseEventListeners: function () {\n var canvas;\n var el = this.el;\n\n canvas = el.sceneEl.canvas;\n canvas.removeEventListener('mousemove', this.onMouseMove);\n canvas.removeEventListener('touchmove', this.onMouseMove);\n el.setAttribute('raycaster', 'useWorldCoordinates', false);\n if (this.data.rayOrigin !== 'mouse') { return; }\n canvas.addEventListener('mousemove', this.onMouseMove, false);\n canvas.addEventListener('touchmove', this.onMouseMove, false);\n el.setAttribute('raycaster', 'useWorldCoordinates', true);\n this.updateCanvasBounds();\n },\n\n onMouseMove: (function () {\n var direction = new THREE.Vector3();\n var mouse = new THREE.Vector2();\n var origin = new THREE.Vector3();\n var rayCasterConfig = {origin: origin, direction: direction};\n\n return function (evt) {\n var bounds = this.canvasBounds;\n var camera = this.el.sceneEl.camera;\n var left;\n var point;\n var top;\n\n camera.parent.updateMatrixWorld();\n\n // Calculate mouse position based on the canvas element\n if (evt.type === 'touchmove' || evt.type === 'touchstart') {\n // Track the first touch for simplicity.\n point = evt.touches.item(0);\n } else {\n point = evt;\n }\n\n left = point.clientX - bounds.left;\n top = point.clientY - bounds.top;\n mouse.x = (left / bounds.width) * 2 - 1;\n mouse.y = -(top / bounds.height) * 2 + 1;\n\n origin.setFromMatrixPosition(camera.matrixWorld);\n direction.set(mouse.x, mouse.y, 0.5).unproject(camera).sub(origin).normalize();\n this.el.setAttribute('raycaster', rayCasterConfig);\n if (evt.type === 'touchmove') { evt.preventDefault(); }\n };\n })(),\n\n /**\n * Trigger mousedown and keep track of the mousedowned entity.\n */\n onCursorDown: function (evt) {\n this.isCursorDown = true;\n // Raycast again for touch.\n if (this.data.rayOrigin === 'mouse' && evt.type === 'touchstart') {\n this.onMouseMove(evt);\n this.el.components.raycaster.checkIntersections();\n evt.preventDefault();\n }\n\n this.twoWayEmit(EVENTS.MOUSEDOWN);\n this.cursorDownEl = this.intersectedEl;\n },\n\n /**\n * Trigger mouseup if:\n * - Not fusing (mobile has no mouse).\n * - Currently intersecting an entity.\n * - Currently-intersected entity is the same as the one when mousedown was triggered,\n * in case user mousedowned one entity, dragged to another, and mouseupped.\n */\n onCursorUp: function (evt) {\n if (!this.isCursorDown) { return; }\n\n this.isCursorDown = false;\n\n var data = this.data;\n this.twoWayEmit(EVENTS.MOUSEUP);\n\n // If intersected entity has changed since the cursorDown, still emit mouseUp on the\n // previously cursorUp entity.\n if (this.cursorDownEl && this.cursorDownEl !== this.intersectedEl) {\n this.intersectedEventDetail.intersection = null;\n this.cursorDownEl.emit(EVENTS.MOUSEUP, this.intersectedEventDetail);\n }\n\n if ((!data.fuse || data.rayOrigin === 'mouse') &&\n this.intersectedEl && this.cursorDownEl === this.intersectedEl) {\n this.twoWayEmit(EVENTS.CLICK);\n }\n\n this.cursorDownEl = null;\n if (evt.type === 'touchend') { evt.preventDefault(); }\n },\n\n /**\n * Handle intersection.\n */\n onIntersection: function (evt) {\n var currentIntersection;\n var cursorEl = this.el;\n var index;\n var intersectedEl;\n var intersection;\n\n // Select closest object, excluding the cursor.\n index = evt.detail.els[0] === cursorEl ? 1 : 0;\n intersection = evt.detail.intersections[index];\n intersectedEl = evt.detail.els[index];\n\n // If cursor is the only intersected object, ignore the event.\n if (!intersectedEl) { return; }\n\n // Already intersecting this entity.\n if (this.intersectedEl === intersectedEl) { return; }\n\n // Ignore events further away than active intersection.\n if (this.intersectedEl) {\n currentIntersection = this.el.components.raycaster.getIntersection(this.intersectedEl);\n if (currentIntersection && currentIntersection.distance <= intersection.distance) { return; }\n }\n\n // Unset current intersection.\n this.clearCurrentIntersection(true);\n\n this.setIntersection(intersectedEl, intersection);\n },\n\n /**\n * Handle intersection cleared.\n */\n onIntersectionCleared: function (evt) {\n var clearedEls = evt.detail.clearedEls;\n // Check if the current intersection has ended\n if (clearedEls.indexOf(this.intersectedEl) === -1) { return; }\n this.clearCurrentIntersection();\n },\n\n setIntersection: function (intersectedEl, intersection) {\n var cursorEl = this.el;\n var data = this.data;\n var self = this;\n\n // Already intersecting.\n if (this.intersectedEl === intersectedEl) { return; }\n\n // Set new intersection.\n this.intersectedEl = intersectedEl;\n\n // Hovering.\n cursorEl.addState(STATES.HOVERING);\n intersectedEl.addState(STATES.HOVERED);\n this.twoWayEmit(EVENTS.MOUSEENTER);\n\n if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') {\n this.el.sceneEl.canvas.classList.add(CANVAS_HOVER_CLASS);\n }\n\n // Begin fuse if necessary.\n if (data.fuseTimeout === 0 || !data.fuse) { return; }\n cursorEl.addState(STATES.FUSING);\n this.twoWayEmit(EVENTS.FUSING);\n this.fuseTimeout = setTimeout(function fuse () {\n cursorEl.removeState(STATES.FUSING);\n self.twoWayEmit(EVENTS.CLICK);\n }, data.fuseTimeout);\n },\n\n clearCurrentIntersection: function (ignoreRemaining) {\n var index;\n var intersection;\n var intersections;\n var cursorEl = this.el;\n\n // Nothing to be cleared.\n if (!this.intersectedEl) { return; }\n\n // No longer hovering (or fusing).\n this.intersectedEl.removeState(STATES.HOVERED);\n cursorEl.removeState(STATES.HOVERING);\n cursorEl.removeState(STATES.FUSING);\n this.twoWayEmit(EVENTS.MOUSELEAVE);\n\n if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') {\n this.el.sceneEl.canvas.classList.remove(CANVAS_HOVER_CLASS);\n }\n\n // Unset intersected entity (after emitting the event).\n this.intersectedEl = null;\n\n // Clear fuseTimeout.\n clearTimeout(this.fuseTimeout);\n\n // Set intersection to another raycasted element if any.\n if (ignoreRemaining === true) { return; }\n intersections = this.el.components.raycaster.intersections;\n if (intersections.length === 0) { return; }\n // Exclude the cursor.\n index = intersections[0].object.el === cursorEl ? 1 : 0;\n intersection = intersections[index];\n if (!intersection) { return; }\n this.setIntersection(intersection.object.el, intersection);\n },\n\n /**\n * Helper to emit on both the cursor and the intersected entity (if exists).\n */\n twoWayEmit: function (evtName) {\n var el = this.el;\n var intersectedEl = this.intersectedEl;\n var intersection;\n\n intersection = this.el.components.raycaster.getIntersection(intersectedEl);\n this.eventDetail.intersectedEl = intersectedEl;\n this.eventDetail.intersection = intersection;\n el.emit(evtName, this.eventDetail);\n\n if (!intersectedEl) { return; }\n\n this.intersectedEventDetail.intersection = intersection;\n intersectedEl.emit(evtName, this.intersectedEventDetail);\n }\n});\n", + "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\nvar utils = require('../utils/');\n\nvar bind = utils.bind;\n\nvar EVENTS = {\n CLICK: 'click',\n FUSING: 'fusing',\n MOUSEENTER: 'mouseenter',\n MOUSEDOWN: 'mousedown',\n MOUSELEAVE: 'mouseleave',\n MOUSEUP: 'mouseup'\n};\n\nvar STATES = {\n FUSING: 'cursor-fusing',\n HOVERING: 'cursor-hovering',\n HOVERED: 'cursor-hovered'\n};\n\nvar CANVAS_EVENTS = {\n DOWN: ['mousedown', 'touchstart'],\n UP: ['mouseup', 'touchend']\n};\n\nvar WEBXR_EVENTS = {\n DOWN: ['selectstart'],\n UP: ['selectend']\n};\n\nvar CANVAS_HOVER_CLASS = 'a-mouse-cursor-hover';\n\n/**\n * Cursor component. Applies the raycaster component specifically for starting the raycaster\n * from the camera and pointing from camera's facing direction, and then only returning the\n * closest intersection. Cursor can be fine-tuned by setting raycaster properties.\n *\n * @member {object} fuseTimeout - Timeout to trigger fuse-click.\n * @member {Element} cursorDownEl - Entity that was last mousedowned during current click.\n * @member {object} intersection - Attributes of the current intersection event, including\n * 3D- and 2D-space coordinates. See: http://threejs.org/docs/api/core/Raycaster.html\n * @member {Element} intersectedEl - Currently-intersected entity. Used to keep track to\n * emit events when unintersecting.\n */\nmodule.exports.Component = registerComponent('cursor', {\n dependencies: ['raycaster'],\n\n schema: {\n downEvents: {default: []},\n fuse: {default: utils.device.isMobile()},\n fuseTimeout: {default: 1500, min: 0},\n mouseCursorStylesEnabled: {default: true},\n upEvents: {default: []},\n rayOrigin: {default: 'entity', oneOf: ['mouse', 'entity']}\n },\n\n init: function () {\n var self = this;\n\n this.fuseTimeout = undefined;\n this.cursorDownEl = null;\n this.intersectedEl = null;\n this.canvasBounds = document.body.getBoundingClientRect();\n this.isCursorDown = false;\n\n // Debounce.\n this.updateCanvasBounds = utils.debounce(function updateCanvasBounds () {\n self.canvasBounds = self.el.sceneEl.canvas.getBoundingClientRect();\n }, 500);\n\n this.eventDetail = {};\n this.intersectedEventDetail = {cursorEl: this.el};\n\n // Bind methods.\n this.onCursorDown = bind(this.onCursorDown, this);\n this.onCursorUp = bind(this.onCursorUp, this);\n this.onIntersection = bind(this.onIntersection, this);\n this.onIntersectionCleared = bind(this.onIntersectionCleared, this);\n this.onMouseMove = bind(this.onMouseMove, this);\n this.onEnterVR = bind(this.onEnterVR, this);\n },\n\n update: function (oldData) {\n if (this.data.rayOrigin === oldData.rayOrigin) { return; }\n this.updateMouseEventListeners();\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n },\n\n remove: function () {\n var el = this.el;\n el.removeState(STATES.HOVERING);\n el.removeState(STATES.FUSING);\n clearTimeout(this.fuseTimeout);\n if (this.intersectedEl) { this.intersectedEl.removeState(STATES.HOVERED); }\n this.removeEventListeners();\n },\n\n addEventListeners: function () {\n var canvas;\n var data = this.data;\n var el = this.el;\n var self = this;\n\n function addCanvasListeners () {\n canvas = el.sceneEl.canvas;\n if (data.downEvents.length || data.upEvents.length) { return; }\n CANVAS_EVENTS.DOWN.forEach(function (downEvent) {\n canvas.addEventListener(downEvent, self.onCursorDown);\n });\n CANVAS_EVENTS.UP.forEach(function (upEvent) {\n canvas.addEventListener(upEvent, self.onCursorUp);\n });\n }\n\n canvas = el.sceneEl.canvas;\n if (canvas) {\n addCanvasListeners();\n } else {\n el.sceneEl.addEventListener('render-target-loaded', addCanvasListeners);\n }\n\n data.downEvents.forEach(function (downEvent) {\n el.addEventListener(downEvent, self.onCursorDown);\n });\n data.upEvents.forEach(function (upEvent) {\n el.addEventListener(upEvent, self.onCursorUp);\n });\n el.addEventListener('raycaster-intersection', this.onIntersection);\n el.addEventListener('raycaster-intersection-cleared', this.onIntersectionCleared);\n\n el.sceneEl.addEventListener('rendererresize', this.updateCanvasBounds);\n el.sceneEl.addEventListener('enter-vr', this.onEnterVR);\n window.addEventListener('resize', this.updateCanvasBounds);\n window.addEventListener('scroll', this.updateCanvasBounds);\n\n this.updateMouseEventListeners();\n },\n\n removeEventListeners: function () {\n var canvas;\n var data = this.data;\n var el = this.el;\n var self = this;\n\n canvas = el.sceneEl.canvas;\n if (canvas && !data.downEvents.length && !data.upEvents.length) {\n CANVAS_EVENTS.DOWN.forEach(function (downEvent) {\n canvas.removeEventListener(downEvent, self.onCursorDown);\n });\n CANVAS_EVENTS.UP.forEach(function (upEvent) {\n canvas.removeEventListener(upEvent, self.onCursorUp);\n });\n }\n\n data.downEvents.forEach(function (downEvent) {\n el.removeEventListener(downEvent, self.onCursorDown);\n });\n data.upEvents.forEach(function (upEvent) {\n el.removeEventListener(upEvent, self.onCursorUp);\n });\n el.removeEventListener('raycaster-intersection', this.onIntersection);\n el.removeEventListener('raycaster-intersection-cleared', this.onIntersectionCleared);\n canvas.removeEventListener('mousemove', this.onMouseMove);\n canvas.removeEventListener('touchstart', this.onMouseMove);\n canvas.removeEventListener('touchmove', this.onMouseMove);\n\n el.sceneEl.removeEventListener('rendererresize', this.updateCanvasBounds);\n el.sceneEl.removeEventListener('enter-vr', this.onEnterVR);\n window.removeEventListener('resize', this.updateCanvasBounds);\n window.removeEventListener('scroll', this.updateCanvasBounds);\n },\n\n updateMouseEventListeners: function () {\n var canvas;\n var el = this.el;\n\n canvas = el.sceneEl.canvas;\n canvas.removeEventListener('mousemove', this.onMouseMove);\n canvas.removeEventListener('touchmove', this.onMouseMove);\n el.setAttribute('raycaster', 'useWorldCoordinates', false);\n if (this.data.rayOrigin !== 'mouse') { return; }\n canvas.addEventListener('mousemove', this.onMouseMove, false);\n canvas.addEventListener('touchmove', this.onMouseMove, false);\n el.setAttribute('raycaster', 'useWorldCoordinates', true);\n this.updateCanvasBounds();\n },\n\n onMouseMove: (function () {\n var direction = new THREE.Vector3();\n var mouse = new THREE.Vector2();\n var origin = new THREE.Vector3();\n var rayCasterConfig = {origin: origin, direction: direction};\n\n return function (evt) {\n var bounds = this.canvasBounds;\n var camera = this.el.sceneEl.camera;\n var left;\n var point;\n var top;\n\n camera.parent.updateMatrixWorld();\n\n // Calculate mouse position based on the canvas element\n if (evt.type === 'touchmove' || evt.type === 'touchstart') {\n // Track the first touch for simplicity.\n point = evt.touches.item(0);\n } else {\n point = evt;\n }\n\n left = point.clientX - bounds.left;\n top = point.clientY - bounds.top;\n mouse.x = (left / bounds.width) * 2 - 1;\n mouse.y = -(top / bounds.height) * 2 + 1;\n\n origin.setFromMatrixPosition(camera.matrixWorld);\n direction.set(mouse.x, mouse.y, 0.5).unproject(camera).sub(origin).normalize();\n this.el.setAttribute('raycaster', rayCasterConfig);\n if (evt.type === 'touchmove') { evt.preventDefault(); }\n };\n })(),\n\n /**\n * Trigger mousedown and keep track of the mousedowned entity.\n */\n onCursorDown: function (evt) {\n this.isCursorDown = true;\n // Raycast again for touch.\n if (this.data.rayOrigin === 'mouse' && evt.type === 'touchstart') {\n this.onMouseMove(evt);\n this.el.components.raycaster.checkIntersections();\n evt.preventDefault();\n }\n\n this.twoWayEmit(EVENTS.MOUSEDOWN);\n this.cursorDownEl = this.intersectedEl;\n },\n\n /**\n * Trigger mouseup if:\n * - Not fusing (mobile has no mouse).\n * - Currently intersecting an entity.\n * - Currently-intersected entity is the same as the one when mousedown was triggered,\n * in case user mousedowned one entity, dragged to another, and mouseupped.\n */\n onCursorUp: function (evt) {\n if (!this.isCursorDown) { return; }\n\n this.isCursorDown = false;\n\n var data = this.data;\n this.twoWayEmit(EVENTS.MOUSEUP);\n\n // If intersected entity has changed since the cursorDown, still emit mouseUp on the\n // previously cursorUp entity.\n if (this.cursorDownEl && this.cursorDownEl !== this.intersectedEl) {\n this.intersectedEventDetail.intersection = null;\n this.cursorDownEl.emit(EVENTS.MOUSEUP, this.intersectedEventDetail);\n }\n\n if ((!data.fuse || data.rayOrigin === 'mouse') &&\n this.intersectedEl && this.cursorDownEl === this.intersectedEl) {\n this.twoWayEmit(EVENTS.CLICK);\n }\n\n this.cursorDownEl = null;\n if (evt.type === 'touchend') { evt.preventDefault(); }\n },\n\n /**\n * Handle intersection.\n */\n onIntersection: function (evt) {\n var currentIntersection;\n var cursorEl = this.el;\n var index;\n var intersectedEl;\n var intersection;\n\n // Select closest object, excluding the cursor.\n index = evt.detail.els[0] === cursorEl ? 1 : 0;\n intersection = evt.detail.intersections[index];\n intersectedEl = evt.detail.els[index];\n\n // If cursor is the only intersected object, ignore the event.\n if (!intersectedEl) { return; }\n\n // Already intersecting this entity.\n if (this.intersectedEl === intersectedEl) { return; }\n\n // Ignore events further away than active intersection.\n if (this.intersectedEl) {\n currentIntersection = this.el.components.raycaster.getIntersection(this.intersectedEl);\n if (currentIntersection && currentIntersection.distance <= intersection.distance) { return; }\n }\n\n // Unset current intersection.\n this.clearCurrentIntersection(true);\n\n this.setIntersection(intersectedEl, intersection);\n },\n\n /**\n * Handle intersection cleared.\n */\n onIntersectionCleared: function (evt) {\n var clearedEls = evt.detail.clearedEls;\n // Check if the current intersection has ended\n if (clearedEls.indexOf(this.intersectedEl) === -1) { return; }\n this.clearCurrentIntersection();\n },\n\n onEnterVR: function () {\n var xrSession = this.el.xrSession;\n var self = this;\n if (!xrSession) { return; }\n WEBXR_EVENTS.DOWN.forEach(function (downEvent) {\n xrSession.addEventListener(downEvent, self.onCursorDown);\n });\n WEBXR_EVENTS.UP.forEach(function (upEvent) {\n xrSession.addEventListener(upEvent, self.onCursorUp);\n });\n },\n\n setIntersection: function (intersectedEl, intersection) {\n var cursorEl = this.el;\n var data = this.data;\n var self = this;\n\n // Already intersecting.\n if (this.intersectedEl === intersectedEl) { return; }\n\n // Set new intersection.\n this.intersectedEl = intersectedEl;\n\n // Hovering.\n cursorEl.addState(STATES.HOVERING);\n intersectedEl.addState(STATES.HOVERED);\n this.twoWayEmit(EVENTS.MOUSEENTER);\n\n if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') {\n this.el.sceneEl.canvas.classList.add(CANVAS_HOVER_CLASS);\n }\n\n // Begin fuse if necessary.\n if (data.fuseTimeout === 0 || !data.fuse) { return; }\n cursorEl.addState(STATES.FUSING);\n this.twoWayEmit(EVENTS.FUSING);\n this.fuseTimeout = setTimeout(function fuse () {\n cursorEl.removeState(STATES.FUSING);\n self.twoWayEmit(EVENTS.CLICK);\n }, data.fuseTimeout);\n },\n\n clearCurrentIntersection: function (ignoreRemaining) {\n var index;\n var intersection;\n var intersections;\n var cursorEl = this.el;\n\n // Nothing to be cleared.\n if (!this.intersectedEl) { return; }\n\n // No longer hovering (or fusing).\n this.intersectedEl.removeState(STATES.HOVERED);\n cursorEl.removeState(STATES.HOVERING);\n cursorEl.removeState(STATES.FUSING);\n this.twoWayEmit(EVENTS.MOUSELEAVE);\n\n if (this.data.mouseCursorStylesEnabled && this.data.rayOrigin === 'mouse') {\n this.el.sceneEl.canvas.classList.remove(CANVAS_HOVER_CLASS);\n }\n\n // Unset intersected entity (after emitting the event).\n this.intersectedEl = null;\n\n // Clear fuseTimeout.\n clearTimeout(this.fuseTimeout);\n\n // Set intersection to another raycasted element if any.\n if (ignoreRemaining === true) { return; }\n intersections = this.el.components.raycaster.intersections;\n if (intersections.length === 0) { return; }\n // Exclude the cursor.\n index = intersections[0].object.el === cursorEl ? 1 : 0;\n intersection = intersections[index];\n if (!intersection) { return; }\n this.setIntersection(intersection.object.el, intersection);\n },\n\n /**\n * Helper to emit on both the cursor and the intersected entity (if exists).\n */\n twoWayEmit: function (evtName) {\n var el = this.el;\n var intersectedEl = this.intersectedEl;\n var intersection;\n\n intersection = this.el.components.raycaster.getIntersection(intersectedEl);\n this.eventDetail.intersectedEl = intersectedEl;\n this.eventDetail.intersection = intersection;\n el.emit(evtName, this.eventDetail);\n\n if (!intersectedEl) { return; }\n\n this.intersectedEventDetail.intersection = intersection;\n intersectedEl.emit(evtName, this.intersectedEventDetail);\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar DAYDREAM_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/google/';\nvar DAYDREAM_CONTROLLER_MODEL_OBJ_URL = DAYDREAM_CONTROLLER_MODEL_BASE_URL + 'vr_controller_daydream.obj';\nvar DAYDREAM_CONTROLLER_MODEL_OBJ_MTL = DAYDREAM_CONTROLLER_MODEL_BASE_URL + 'vr_controller_daydream.mtl';\n\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'google-daydream';\nvar GAMEPAD_ID_WEBVR = 'Daydream Controller';\n\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n/**\n * Daydream controls.\n * Interface with Daydream controller and map Gamepad events to\n * controller buttons: trackpad, menu, system\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('daydream-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n buttonColor: {type: 'color', default: '#000000'},\n buttonTouchedColor: {type: 'color', default: '#777777'},\n buttonHighlightColor: {type: 'color', default: '#FFFFFF'},\n model: {default: true},\n orientationOffset: {type: 'vec3'},\n armModel: {default: true}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - menu (never dispatched on this layer)\n * 2 - system (never dispatched on this layer)\n */\n mapping: {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'menu', 'system']\n },\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, {hand: this.data.hand});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n el.setAttribute('tracked-controls', {\n armModel: data.armModel,\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset\n });\n if (!this.data.model) { return; }\n this.el.setAttribute('obj-model', {\n obj: DAYDREAM_CONTROLLER_MODEL_OBJ_URL,\n mtl: DAYDREAM_CONTROLLER_MODEL_OBJ_MTL\n });\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n if (!this.data.model) { return; }\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.menu = controllerObject3D.getObjectByName('AppButton_AppButton_Cylinder.004');\n buttonMeshes.system = controllerObject3D.getObjectByName('HomeButton_HomeButton_Cylinder.005');\n buttonMeshes.trackpad = controllerObject3D.getObjectByName('TouchPad_TouchPad_Cylinder.003');\n // Offset pivot point.\n controllerObject3D.position.set(0, 0, -0.04);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var buttonMeshes = this.buttonMeshes;\n if (!buttonMeshes || !buttonMeshes[buttonName]) { return; }\n var color;\n switch (state) {\n case 'down':\n color = this.data.buttonHighlightColor;\n break;\n case 'touchstart':\n color = this.data.buttonTouchedColor;\n break;\n default:\n color = this.data.buttonColor;\n }\n buttonMeshes[buttonName].material.color.set(color);\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GEARVR_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/samsung/';\nvar GEARVR_CONTROLLER_MODEL_OBJ_URL = GEARVR_CONTROLLER_MODEL_BASE_URL + 'gear_vr_controller.obj';\nvar GEARVR_CONTROLLER_MODEL_OBJ_MTL = GEARVR_CONTROLLER_MODEL_BASE_URL + 'gear_vr_controller.mtl';\n\nvar GAMEPAD_ID_WEBXR = 'samsung-gearvr';\nvar GAMEPAD_ID_WEBVR = 'Gear VR';\n\n// Prefix for Gen1 and Gen2 Oculus Touch Controllers.\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n/**\n * Button indices:\n * 0 - trackpad\n * 1 - trigger\n *\n * Axis:\n * 0 - trackpad x\n * 1 - trackpad y\n */\nvar INPUT_MAPPING_WEBVR = {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'trigger']\n};\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - none\n * 2 - touchpad\n * 3 - menu\n *\n * Axis:\n * 0 - touchpad x\n * 1 - touchpad y\n * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-go.json\n */\nvar INPUT_MAPPING_WEBXR = {\n left: {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'none', 'touchpad', 'menu']\n },\n right: {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'none', 'touchpad', 'menu']\n }\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Gear VR controls.\n * Interface with Gear VR controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('gearvr-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n buttonColor: {type: 'color', default: '#000000'},\n buttonTouchedColor: {type: 'color', default: '#777777'},\n buttonHighlightColor: {type: 'color', default: '#FFFFFF'},\n model: {default: true},\n orientationOffset: {type: 'vec3'},\n armModel: {default: true}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX,\n this.data.hand ? {hand: this.data.hand} : {});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n el.setAttribute('tracked-controls', {\n armModel: data.armModel,\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n id: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset\n });\n if (!this.data.model) { return; }\n this.el.setAttribute('obj-model', {\n obj: GEARVR_CONTROLLER_MODEL_OBJ_URL,\n mtl: GEARVR_CONTROLLER_MODEL_OBJ_MTL\n });\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n // No need for onButtonChanged, since Gear VR controller has no analog buttons.\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n if (!this.data.model) { return; }\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.trigger = controllerObject3D.children[2];\n buttonMeshes.trackpad = controllerObject3D.children[1];\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var buttonMeshes = this.buttonMeshes;\n if (!buttonMeshes || !buttonMeshes[buttonName]) { return; }\n var color;\n switch (state) {\n case 'down':\n color = this.data.buttonHighlightColor;\n break;\n case 'touchstart':\n color = this.data.buttonTouchedColor;\n break;\n default:\n color = this.data.buttonColor;\n }\n buttonMeshes[buttonName].material.color.set(color);\n }\n});\n", - "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar GAMEPAD_ID_PREFIX = 'generic';\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - squeeze\n * 2 - touchpad\n * 3 - thumbstick\n *\n * Axis:\n * 0 - touchpad\n * 1 - thumbstick\n *\n */\nvar INPUT_MAPPING = {\n axes: {\n touchpad: [0, 1],\n thumbstick: [2, 3]\n },\n buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick']\n};\n\n/**\n * Oculus Go controls.\n * Interface with Oculus Go controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('generic-tracked-controller-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n defaultModel: {default: true},\n defaultModelColor: {default: 'gray'},\n orientationOffset: {type: 'vec3'}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n var data = this.data;\n var hand = data.hand ? data.hand : undefined;\n checkControllerPresentAndSetup(\n this, GAMEPAD_ID_PREFIX,\n {hand: hand, iterateControllerProfiles: true});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n // Do nothing if tracked-controls already set.\n // Generic controls have the lowest precedence.\n if (this.el.components['tracked-controls']) { return; }\n el.setAttribute('tracked-controls', {\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset,\n iterateControllerProfiles: true\n });\n if (!this.data.defaultModel) { return; }\n this.initDefaultModel();\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n initDefaultModel: function () {\n var modelEl = this.modelEl = document.createElement('a-entity');\n modelEl.setAttribute('geometry', {\n primitive: 'sphere',\n radius: 0.03\n });\n modelEl.setAttribute('material', {color: this.data.color});\n this.el.appendChild(modelEl);\n }\n});\n", + "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar GAMEPAD_ID_PREFIX = 'generic';\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - squeeze\n * 2 - touchpad\n * 3 - thumbstick\n *\n * Axis:\n * 0 - touchpad\n * 1 - thumbstick\n *\n */\nvar INPUT_MAPPING = {\n axes: {\n touchpad: [0, 1],\n thumbstick: [2, 3]\n },\n buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick']\n};\n\n/**\n * Oculus Go controls.\n * Interface with Oculus Go controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('generic-tracked-controller-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n defaultModel: {default: true},\n defaultModelColor: {default: 'gray'},\n orientationOffset: {type: 'vec3'}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n var data = this.data;\n var hand = data.hand ? data.hand : undefined;\n checkControllerPresentAndSetup(\n this, GAMEPAD_ID_PREFIX,\n {hand: hand, iterateControllerProfiles: true});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n // Do nothing if tracked-controls already set.\n // Generic controls have the lowest precedence.\n if (this.el.components['tracked-controls']) { return; }\n el.setAttribute('tracked-controls', {\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset,\n iterateControllerProfiles: true\n });\n if (!this.data.defaultModel) { return; }\n this.initDefaultModel();\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n initDefaultModel: function () {\n var modelEl = this.modelEl = document.createElement('a-entity');\n modelEl.setAttribute('geometry', {\n primitive: 'sphere',\n radius: 0.03\n });\n modelEl.setAttribute('material', {color: this.data.color});\n this.el.appendChild(modelEl);\n }\n});\n", "var geometries = require('../core/geometry').geometries;\nvar geometryNames = require('../core/geometry').geometryNames;\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\n\nvar dummyGeometry = new THREE.Geometry();\n\n/**\n * Geometry component. Combined with material component to make a mesh in 3D object.\n * Extended with registered geometries.\n */\nmodule.exports.Component = registerComponent('geometry', {\n schema: {\n buffer: {default: true},\n primitive: {default: 'box', oneOf: geometryNames, schemaChange: true},\n skipCache: {default: false}\n },\n\n init: function () {\n this.geometry = null;\n },\n\n /**\n * Talk to geometry system to get or create geometry.\n */\n update: function (previousData) {\n var data = this.data;\n var el = this.el;\n var mesh;\n var system = this.system;\n\n // Dispose old geometry if we created one.\n if (this.geometry) {\n system.unuseGeometry(previousData);\n this.geometry = null;\n }\n\n // Create new geometry.\n this.geometry = system.getOrCreateGeometry(data);\n\n // Set on mesh. If mesh does not exist, create it.\n mesh = el.getObject3D('mesh');\n if (mesh) {\n mesh.geometry = this.geometry;\n } else {\n mesh = new THREE.Mesh();\n mesh.geometry = this.geometry;\n el.setObject3D('mesh', mesh);\n }\n },\n\n /**\n * Tell geometry system that entity is no longer using the geometry.\n * Unset the geometry on the mesh\n */\n remove: function () {\n this.system.unuseGeometry(this.data);\n this.el.getObject3D('mesh').geometry = dummyGeometry;\n this.geometry = null;\n },\n\n /**\n * Update geometry component schema based on geometry type.\n */\n updateSchema: function (data) {\n var currentGeometryType = this.oldData && this.oldData.primitive;\n var newGeometryType = data.primitive;\n var schema = geometries[newGeometryType] && geometries[newGeometryType].schema;\n\n // Geometry has no schema.\n if (!schema) { throw new Error('Unknown geometry schema `' + newGeometryType + '`'); }\n // Nothing has changed.\n if (currentGeometryType && currentGeometryType === newGeometryType) { return; }\n\n this.extendSchema(schema);\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\nvar warn = utils.debug('components:gltf-model:warn');\n\n/**\n * glTF model loader.\n */\nmodule.exports.Component = registerComponent('gltf-model', {\n schema: {type: 'model'},\n\n init: function () {\n var dracoLoader = this.system.getDRACOLoader();\n this.model = null;\n this.loader = new THREE.GLTFLoader();\n if (dracoLoader) {\n this.loader.setDRACOLoader(dracoLoader);\n }\n },\n\n update: function () {\n var self = this;\n var el = this.el;\n var src = this.data;\n\n if (!src) { return; }\n\n this.remove();\n\n this.loader.load(src, function gltfLoaded (gltfModel) {\n self.model = gltfModel.scene || gltfModel.scenes[0];\n self.model.animations = gltfModel.animations;\n el.setObject3D('mesh', self.model);\n el.emit('model-loaded', {format: 'gltf', model: self.model});\n }, undefined /* onProgress */, function gltfFailed (error) {\n var message = (error && error.message) ? error.message : 'Failed to load glTF model';\n warn(message);\n el.emit('model-error', {format: 'gltf', src: src});\n });\n },\n\n remove: function () {\n if (!this.model) { return; }\n this.el.removeObject3D('mesh');\n }\n});\n", - "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\n\n// Found at https://github.com/aframevr/assets.\nvar MODEL_URLS = {\n left: 'https://cdn.aframe.io/controllers/hands/leftHand.glb',\n right: 'https://cdn.aframe.io/controllers/hands/rightHand.glb'\n};\n\n// Poses.\nvar ANIMATIONS = {\n open: 'Open',\n // point: grip active, trackpad surface active, trigger inactive.\n point: 'Point',\n // pointThumb: grip active, trigger inactive, trackpad surface inactive.\n pointThumb: 'Point + Thumb',\n // fist: grip active, trigger active, trackpad surface active.\n fist: 'Fist',\n // hold: trigger active, grip inactive.\n hold: 'Hold',\n // thumbUp: grip active, trigger active, trackpad surface inactive.\n thumbUp: 'Thumb Up'\n};\n\n// Map animation to public events for the API.\nvar EVENTS = {};\nEVENTS[ANIMATIONS.fist] = 'grip';\nEVENTS[ANIMATIONS.thumbUp] = 'pistol';\nEVENTS[ANIMATIONS.point] = 'pointing';\n\n/**\n * Hand controls component that abstracts 6DoF controls:\n * oculus-touch-controls, vive-controls, windows-motion-controls.\n *\n * Originally meant to be a sample implementation of applications-specific controls that\n * abstracts multiple types of controllers.\n *\n * Auto-detect appropriate controller.\n * Handle common events coming from the detected vendor-specific controls.\n * Translate button events to semantic hand-related event names:\n * (gripclose, gripopen, thumbup, thumbdown, pointup, pointdown)\n * Load hand model with gestures that are applied based on the button pressed.\n *\n * @property {string} Hand mapping (`left`, `right`).\n */\nmodule.exports.Component = registerComponent('hand-controls', {\n schema: {default: 'left'},\n\n init: function () {\n var self = this;\n var el = this.el;\n // Current pose.\n this.gesture = ANIMATIONS.open;\n // Active buttons populated by events provided by the attached controls.\n this.pressedButtons = {};\n this.touchedButtons = {};\n this.loader = new THREE.GLTFLoader();\n this.loader.setCrossOrigin('anonymous');\n\n this.onGripDown = function () { self.handleButton('grip', 'down'); };\n this.onGripUp = function () { self.handleButton('grip', 'up'); };\n this.onTrackpadDown = function () { self.handleButton('trackpad', 'down'); };\n this.onTrackpadUp = function () { self.handleButton('trackpad', 'up'); };\n this.onTrackpadTouchStart = function () { self.handleButton('trackpad', 'touchstart'); };\n this.onTrackpadTouchEnd = function () { self.handleButton('trackpad', 'touchend'); };\n this.onTriggerDown = function () { self.handleButton('trigger', 'down'); };\n this.onTriggerUp = function () { self.handleButton('trigger', 'up'); };\n this.onTriggerTouchStart = function () { self.handleButton('trigger', 'touchstart'); };\n this.onTriggerTouchEnd = function () { self.handleButton('trigger', 'touchend'); };\n this.onGripTouchStart = function () { self.handleButton('grip', 'touchstart'); };\n this.onGripTouchEnd = function () { self.handleButton('grip', 'touchend'); };\n this.onThumbstickDown = function () { self.handleButton('thumbstick', 'down'); };\n this.onThumbstickUp = function () { self.handleButton('thumbstick', 'up'); };\n this.onAorXTouchStart = function () { self.handleButton('AorX', 'touchstart'); };\n this.onAorXTouchEnd = function () { self.handleButton('AorX', 'touchend'); };\n this.onBorYTouchStart = function () { self.handleButton('BorY', 'touchstart'); };\n this.onBorYTouchEnd = function () { self.handleButton('BorY', 'touchend'); };\n this.onSurfaceTouchStart = function () { self.handleButton('surface', 'touchstart'); };\n this.onSurfaceTouchEnd = function () { self.handleButton('surface', 'touchend'); };\n this.onControllerConnected = this.onControllerConnected.bind(this);\n this.onControllerDisconnected = this.onControllerDisconnected.bind(this);\n\n el.addEventListener('controllerconnected', this.onControllerConnected);\n el.addEventListener('controllerdisconnected', this.onControllerDisconnected);\n\n // Hidden by default.\n el.object3D.visible = false;\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n },\n\n tick: function (time, delta) {\n var mesh = this.el.getObject3D('mesh');\n\n if (!mesh || !mesh.mixer) { return; }\n\n mesh.mixer.update(delta / 1000);\n },\n\n onControllerConnected: function () {\n this.el.object3D.visible = true;\n },\n\n onControllerDisconnected: function () {\n this.el.object3D.visible = false;\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('gripdown', this.onGripDown);\n el.addEventListener('gripup', this.onGripUp);\n el.addEventListener('trackpaddown', this.onTrackpadDown);\n el.addEventListener('trackpadup', this.onTrackpadUp);\n el.addEventListener('trackpadtouchstart', this.onTrackpadTouchStart);\n el.addEventListener('trackpadtouchend', this.onTrackpadTouchEnd);\n el.addEventListener('triggerdown', this.onTriggerDown);\n el.addEventListener('triggerup', this.onTriggerUp);\n el.addEventListener('triggertouchstart', this.onTriggerTouchStart);\n el.addEventListener('triggertouchend', this.onTriggerTouchEnd);\n el.addEventListener('griptouchstart', this.onGripTouchStart);\n el.addEventListener('griptouchend', this.onGripTouchEnd);\n el.addEventListener('thumbstickdown', this.onThumbstickDown);\n el.addEventListener('thumbstickup', this.onThumbstickUp);\n el.addEventListener('abuttontouchstart', this.onAorXTouchStart);\n el.addEventListener('abuttontouchend', this.onAorXTouchEnd);\n el.addEventListener('bbuttontouchstart', this.onBorYTouchStart);\n el.addEventListener('bbuttontouchend', this.onBorYTouchEnd);\n el.addEventListener('xbuttontouchstart', this.onAorXTouchStart);\n el.addEventListener('xbuttontouchend', this.onAorXTouchEnd);\n el.addEventListener('ybuttontouchstart', this.onBorYTouchStart);\n el.addEventListener('ybuttontouchend', this.onBorYTouchEnd);\n el.addEventListener('surfacetouchstart', this.onSurfaceTouchStart);\n el.addEventListener('surfacetouchend', this.onSurfaceTouchEnd);\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('gripdown', this.onGripDown);\n el.removeEventListener('gripup', this.onGripUp);\n el.removeEventListener('trackpaddown', this.onTrackpadDown);\n el.removeEventListener('trackpadup', this.onTrackpadUp);\n el.removeEventListener('trackpadtouchstart', this.onTrackpadTouchStart);\n el.removeEventListener('trackpadtouchend', this.onTrackpadTouchEnd);\n el.removeEventListener('triggerdown', this.onTriggerDown);\n el.removeEventListener('triggerup', this.onTriggerUp);\n el.removeEventListener('triggertouchstart', this.onTriggerTouchStart);\n el.removeEventListener('triggertouchend', this.onTriggerTouchEnd);\n el.removeEventListener('griptouchstart', this.onGripTouchStart);\n el.removeEventListener('griptouchend', this.onGripTouchEnd);\n el.removeEventListener('thumbstickdown', this.onThumbstickDown);\n el.removeEventListener('thumbstickup', this.onThumbstickUp);\n el.removeEventListener('abuttontouchstart', this.onAorXTouchStart);\n el.removeEventListener('abuttontouchend', this.onAorXTouchEnd);\n el.removeEventListener('bbuttontouchstart', this.onBorYTouchStart);\n el.removeEventListener('bbuttontouchend', this.onBorYTouchEnd);\n el.removeEventListener('xbuttontouchstart', this.onAorXTouchStart);\n el.removeEventListener('xbuttontouchend', this.onAorXTouchEnd);\n el.removeEventListener('ybuttontouchstart', this.onBorYTouchStart);\n el.removeEventListener('ybuttontouchend', this.onBorYTouchEnd);\n el.removeEventListener('surfacetouchstart', this.onSurfaceTouchStart);\n el.removeEventListener('surfacetouchend', this.onSurfaceTouchEnd);\n },\n\n /**\n * Update handler. More like the `init` handler since the only property is the hand, and\n * that won't be changing much.\n */\n update: function (previousHand) {\n var controlConfiguration;\n var el = this.el;\n var hand = this.data;\n var self = this;\n\n // Get common configuration to abstract different vendor controls.\n controlConfiguration = {\n hand: hand,\n model: false,\n orientationOffset: {x: 0, y: 0, z: hand === 'left' ? 90 : -90}\n };\n\n // Set model.\n if (hand !== previousHand) {\n this.loader.load(MODEL_URLS[hand], function (gltf) {\n var mesh = gltf.scene.children[0];\n mesh.mixer = new THREE.AnimationMixer(mesh);\n self.clips = gltf.animations;\n el.setObject3D('mesh', mesh);\n mesh.position.set(0, 0, 0);\n mesh.rotation.set(0, 0, 0);\n el.setAttribute('vive-controls', controlConfiguration);\n el.setAttribute('oculus-touch-controls', controlConfiguration);\n el.setAttribute('windows-motion-controls', controlConfiguration);\n });\n }\n },\n\n remove: function () {\n this.el.removeObject3D('mesh');\n },\n\n /**\n * Play model animation, based on which button was pressed and which kind of event.\n *\n * 1. Process buttons.\n * 2. Determine gesture (this.determineGesture()).\n * 3. Animation gesture (this.animationGesture()).\n * 4. Emit gesture events (this.emitGestureEvents()).\n *\n * @param {string} button - Name of the button.\n * @param {string} evt - Type of event for the button (i.e., down/up/touchstart/touchend).\n */\n handleButton: function (button, evt) {\n var lastGesture;\n var isPressed = evt === 'down';\n var isTouched = evt === 'touchstart';\n\n // Update objects.\n if (evt.indexOf('touch') === 0) {\n // Update touch object.\n if (isTouched === this.touchedButtons[button]) { return; }\n this.touchedButtons[button] = isTouched;\n } else {\n // Update button object.\n if (isPressed === this.pressedButtons[button]) { return; }\n this.pressedButtons[button] = isPressed;\n }\n\n // Determine the gesture.\n lastGesture = this.gesture;\n this.gesture = this.determineGesture();\n\n // Same gesture.\n if (this.gesture === lastGesture) { return; }\n // Animate gesture.\n this.animateGesture(this.gesture, lastGesture);\n\n // Emit events.\n this.emitGestureEvents(this.gesture, lastGesture);\n },\n\n /**\n * Determine which pose hand should be in considering active and touched buttons.\n */\n determineGesture: function () {\n var gesture;\n var isGripActive = this.pressedButtons['grip'];\n var isSurfaceActive = this.pressedButtons['surface'] || this.touchedButtons['surface'];\n var isTrackpadActive = this.pressedButtons['trackpad'] || this.touchedButtons['trackpad'];\n var isTriggerActive = this.pressedButtons['trigger'] || this.touchedButtons['trigger'];\n var isABXYActive = this.touchedButtons['AorX'] || this.touchedButtons['BorY'];\n var isVive = isViveController(this.el.components['tracked-controls']);\n\n // Works well with Oculus Touch and Windows Motion Controls, but Vive needs tweaks.\n if (isVive) {\n if (isGripActive || isTriggerActive) {\n gesture = ANIMATIONS.fist;\n } else if (isTrackpadActive) {\n gesture = ANIMATIONS.point;\n }\n } else {\n if (isGripActive) {\n if (isSurfaceActive || isABXYActive || isTrackpadActive) {\n gesture = isTriggerActive ? ANIMATIONS.fist : ANIMATIONS.point;\n } else {\n gesture = isTriggerActive ? ANIMATIONS.thumbUp : ANIMATIONS.pointThumb;\n }\n } else if (isTriggerActive) {\n gesture = ANIMATIONS.hold;\n }\n }\n\n return gesture;\n },\n\n /**\n * Play corresponding clip to a gesture\n */\n getClip: function (gesture) {\n var clip;\n var i;\n for (i = 0; i < this.clips.length; i++) {\n clip = this.clips[i];\n if (clip.name !== gesture) { continue; }\n return clip;\n }\n },\n\n /**\n * Play gesture animation.\n *\n * @param {string} gesture - Which pose to animate to. If absent, then animate to open.\n * @param {string} lastGesture - Previous gesture, to reverse back to open if needed.\n */\n animateGesture: function (gesture, lastGesture) {\n if (gesture) {\n this.playAnimation(gesture || ANIMATIONS.open, lastGesture, false);\n return;\n }\n\n // If no gesture, then reverse the current gesture back to open pose.\n this.playAnimation(lastGesture, lastGesture, true);\n },\n\n /**\n * Emit `hand-controls`-specific events.\n */\n emitGestureEvents: function (gesture, lastGesture) {\n var el = this.el;\n var eventName;\n\n if (lastGesture === gesture) { return; }\n\n // Emit event for lastGesture not inactive.\n eventName = getGestureEventName(lastGesture, false);\n if (eventName) { el.emit(eventName); }\n\n // Emit event for current gesture now active.\n eventName = getGestureEventName(gesture, true);\n if (eventName) { el.emit(eventName); }\n },\n\n/**\n * Play hand animation based on button state.\n *\n * @param {string} gesture - Name of the animation as specified by the model.\n * @param {string} lastGesture - Previous pose.\n * @param {boolean} reverse - Whether animation should play in reverse.\n */\n playAnimation: function (gesture, lastGesture, reverse) {\n var clip;\n var fromAction;\n var mesh = this.el.getObject3D('mesh');\n var toAction;\n\n if (!mesh) { return; }\n\n // Stop all current animations.\n mesh.mixer.stopAllAction();\n\n // Grab clip action.\n clip = this.getClip(gesture);\n toAction = mesh.mixer.clipAction(clip);\n toAction.clampWhenFinished = true;\n toAction.loop = THREE.LoopRepeat;\n toAction.repetitions = 0;\n toAction.timeScale = reverse ? -1 : 1;\n toAction.time = reverse ? clip.duration : 0;\n toAction.weight = 1;\n\n // No gesture to gesture or gesture to no gesture.\n if (!lastGesture || gesture === lastGesture) {\n // Stop all current animations.\n mesh.mixer.stopAllAction();\n // Play animation.\n toAction.play();\n return;\n }\n\n // Animate or crossfade from gesture to gesture.\n clip = this.getClip(lastGesture);\n fromAction = mesh.mixer.clipAction(clip);\n fromAction.weight = 0.15;\n fromAction.play();\n toAction.play();\n fromAction.crossFadeTo(toAction, 0.15, true);\n }\n});\n\n/**\n * Suffix gestures based on toggle state (e.g., open/close, up/down, start/end).\n *\n * @param {string} gesture\n * @param {boolean} active\n */\nfunction getGestureEventName (gesture, active) {\n var eventName;\n\n if (!gesture) { return; }\n\n eventName = EVENTS[gesture];\n if (eventName === 'grip') {\n return eventName + (active ? 'close' : 'open');\n }\n if (eventName === 'point') {\n return eventName + (active ? 'up' : 'down');\n }\n if (eventName === 'pointing' || eventName === 'pistol') {\n return eventName + (active ? 'start' : 'end');\n }\n return;\n}\n\nfunction isViveController (trackedControls) {\n var controller = trackedControls && trackedControls.controller;\n var isVive = controller && (controller.id && controller.id.indexOf('OpenVR ') === 0 ||\n (controller.profiles &&\n controller.profiles[0] &&\n controller.profiles[0] === 'htc-vive-controller-mv'));\n return isVive;\n}\n", - "require('./animation');\nrequire('./camera');\nrequire('./cursor');\nrequire('./daydream-controls');\nrequire('./gearvr-controls');\nrequire('./geometry');\nrequire('./generic-tracked-controller-controls');\nrequire('./gltf-model');\nrequire('./hand-controls');\nrequire('./laser-controls');\nrequire('./light');\nrequire('./line');\nrequire('./link');\nrequire('./look-controls');\nrequire('./material');\nrequire('./obj-model');\nrequire('./oculus-go-controls');\nrequire('./oculus-touch-controls');\nrequire('./position');\nrequire('./raycaster');\nrequire('./rotation');\nrequire('./scale');\nrequire('./shadow');\nrequire('./sound');\nrequire('./text');\nrequire('./tracked-controls');\nrequire('./tracked-controls-webvr');\nrequire('./tracked-controls-webxr');\nrequire('./visible');\nrequire('./vive-controls');\nrequire('./vive-focus-controls');\nrequire('./wasd-controls');\nrequire('./windows-motion-controls');\n\nrequire('./scene/background');\nrequire('./scene/debug');\nrequire('./scene/device-orientation-permission-ui');\nrequire('./scene/embedded');\nrequire('./scene/inspector');\nrequire('./scene/fog');\nrequire('./scene/keyboard-shortcuts');\nrequire('./scene/pool');\nrequire('./scene/screenshot');\nrequire('./scene/stats');\nrequire('./scene/vr-mode-ui');\n", - "var registerComponent = require('../core/component').registerComponent;\nvar utils = require('../utils/');\n\nregisterComponent('laser-controls', {\n schema: {\n hand: {default: 'right'},\n model: {default: true},\n defaultModelColor: {type: 'color', default: 'grey'}\n },\n\n init: function () {\n var config = this.config;\n var data = this.data;\n var el = this.el;\n var self = this;\n var controlsConfiguration = {hand: data.hand, model: data.model};\n\n // Set all controller models.\n el.setAttribute('daydream-controls', controlsConfiguration);\n el.setAttribute('gearvr-controls', controlsConfiguration);\n el.setAttribute('oculus-go-controls', controlsConfiguration);\n el.setAttribute('oculus-touch-controls', controlsConfiguration);\n el.setAttribute('vive-controls', controlsConfiguration);\n el.setAttribute('vive-focus-controls', controlsConfiguration);\n el.setAttribute('windows-motion-controls', controlsConfiguration);\n el.setAttribute('generic-tracked-controller-controls', controlsConfiguration);\n\n // Wait for controller to connect, or have a valid pointing pose, before creating ray\n el.addEventListener('controllerconnected', createRay);\n el.addEventListener('controllerdisconnected', hideRay);\n el.addEventListener('controllermodelready', function (evt) {\n createRay(evt);\n self.modelReady = true;\n });\n\n function createRay (evt) {\n var controllerConfig = config[evt.detail.name];\n\n if (!controllerConfig) { return; }\n\n // Show the line unless a particular config opts to hide it, until a controllermodelready\n // event comes through.\n var raycasterConfig = utils.extend({\n showLine: true\n }, controllerConfig.raycaster || {});\n\n // The controllermodelready event contains a rayOrigin that takes into account\n // offsets specific to the loaded model.\n if (evt.detail.rayOrigin) {\n raycasterConfig.origin = evt.detail.rayOrigin.origin;\n raycasterConfig.direction = evt.detail.rayOrigin.direction;\n raycasterConfig.showLine = true;\n }\n\n // Only apply a default raycaster if it does not yet exist. This prevents it overwriting\n // config applied from a controllermodelready event.\n if (evt.detail.rayOrigin || !self.modelReady) {\n el.setAttribute('raycaster', raycasterConfig);\n } else {\n el.setAttribute('raycaster', 'showLine', true);\n }\n\n el.setAttribute('cursor', utils.extend({\n fuse: false\n }, controllerConfig.cursor));\n }\n\n function hideRay () {\n el.setAttribute('raycaster', 'showLine', false);\n }\n },\n\n config: {\n 'daydream-controls': {\n cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']}\n },\n\n 'gearvr-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0.0010, z: 0}}\n },\n\n 'generic-tracked-controller-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']}\n },\n\n 'oculus-go-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0.0005, z: 0}}\n },\n\n 'oculus-touch-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0, z: 0}}\n },\n\n 'vive-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']}\n },\n\n 'vive-focus-controls': {\n cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']}\n },\n\n 'windows-motion-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {showLine: false}\n }\n }\n});\n", + "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\n\n// Found at https://github.com/aframevr/assets.\nvar MODEL_URLS = {\n toonLeft: 'https://cdn.aframe.io/controllers/hands/leftHand.glb',\n toonRight: 'https://cdn.aframe.io/controllers/hands/rightHand.glb',\n lowPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandLow.glb',\n lowPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandLow.glb',\n highPolyLeft: 'https://cdn.aframe.io/controllers/hands/leftHandHigh.glb',\n highPolyRight: 'https://cdn.aframe.io/controllers/hands/rightHandHigh.glb'\n};\n\n// Poses.\nvar ANIMATIONS = {\n open: 'Open',\n // point: grip active, trackpad surface active, trigger inactive.\n point: 'Point',\n // pointThumb: grip active, trigger inactive, trackpad surface inactive.\n pointThumb: 'Point + Thumb',\n // fist: grip active, trigger active, trackpad surface active.\n fist: 'Fist',\n // hold: trigger active, grip inactive.\n hold: 'Hold',\n // thumbUp: grip active, trigger active, trackpad surface inactive.\n thumbUp: 'Thumb Up'\n};\n\n// Map animation to public events for the API.\nvar EVENTS = {};\nEVENTS[ANIMATIONS.fist] = 'grip';\nEVENTS[ANIMATIONS.thumbUp] = 'pistol';\nEVENTS[ANIMATIONS.point] = 'pointing';\n\n/**\n * Hand controls component that abstracts 6DoF controls:\n * oculus-touch-controls, vive-controls, windows-motion-controls.\n *\n * Originally meant to be a sample implementation of applications-specific controls that\n * abstracts multiple types of controllers.\n *\n * Auto-detect appropriate controller.\n * Handle common events coming from the detected vendor-specific controls.\n * Translate button events to semantic hand-related event names:\n * (gripclose, gripopen, thumbup, thumbdown, pointup, pointdown)\n * Load hand model with gestures that are applied based on the button pressed.\n *\n * @property {string} Hand mapping (`left`, `right`).\n */\nmodule.exports.Component = registerComponent('hand-controls', {\n schema: {\n color: {default: 'white', type: 'color'},\n hand: { default: 'left' },\n handModelStyle: {default: 'lowPoly', oneOf: ['lowPoly', 'highPoly', 'toon']}\n },\n\n init: function () {\n var self = this;\n var el = this.el;\n // Current pose.\n this.gesture = ANIMATIONS.open;\n // Active buttons populated by events provided by the attached controls.\n this.pressedButtons = {};\n this.touchedButtons = {};\n this.loader = new THREE.GLTFLoader();\n this.loader.setCrossOrigin('anonymous');\n\n this.onGripDown = function () { self.handleButton('grip', 'down'); };\n this.onGripUp = function () { self.handleButton('grip', 'up'); };\n this.onTrackpadDown = function () { self.handleButton('trackpad', 'down'); };\n this.onTrackpadUp = function () { self.handleButton('trackpad', 'up'); };\n this.onTrackpadTouchStart = function () { self.handleButton('trackpad', 'touchstart'); };\n this.onTrackpadTouchEnd = function () { self.handleButton('trackpad', 'touchend'); };\n this.onTriggerDown = function () { self.handleButton('trigger', 'down'); };\n this.onTriggerUp = function () { self.handleButton('trigger', 'up'); };\n this.onTriggerTouchStart = function () { self.handleButton('trigger', 'touchstart'); };\n this.onTriggerTouchEnd = function () { self.handleButton('trigger', 'touchend'); };\n this.onGripTouchStart = function () { self.handleButton('grip', 'touchstart'); };\n this.onGripTouchEnd = function () { self.handleButton('grip', 'touchend'); };\n this.onThumbstickDown = function () { self.handleButton('thumbstick', 'down'); };\n this.onThumbstickUp = function () { self.handleButton('thumbstick', 'up'); };\n this.onAorXTouchStart = function () { self.handleButton('AorX', 'touchstart'); };\n this.onAorXTouchEnd = function () { self.handleButton('AorX', 'touchend'); };\n this.onBorYTouchStart = function () { self.handleButton('BorY', 'touchstart'); };\n this.onBorYTouchEnd = function () { self.handleButton('BorY', 'touchend'); };\n this.onSurfaceTouchStart = function () { self.handleButton('surface', 'touchstart'); };\n this.onSurfaceTouchEnd = function () { self.handleButton('surface', 'touchend'); };\n this.onControllerConnected = this.onControllerConnected.bind(this);\n this.onControllerDisconnected = this.onControllerDisconnected.bind(this);\n\n el.addEventListener('controllerconnected', this.onControllerConnected);\n el.addEventListener('controllerdisconnected', this.onControllerDisconnected);\n\n // Hidden by default.\n el.object3D.visible = false;\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n },\n\n tick: function (time, delta) {\n var mesh = this.el.getObject3D('mesh');\n\n if (!mesh || !mesh.mixer) { return; }\n\n mesh.mixer.update(delta / 1000);\n },\n\n onControllerConnected: function () {\n this.el.object3D.visible = true;\n },\n\n onControllerDisconnected: function () {\n this.el.object3D.visible = false;\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('gripdown', this.onGripDown);\n el.addEventListener('gripup', this.onGripUp);\n el.addEventListener('trackpaddown', this.onTrackpadDown);\n el.addEventListener('trackpadup', this.onTrackpadUp);\n el.addEventListener('trackpadtouchstart', this.onTrackpadTouchStart);\n el.addEventListener('trackpadtouchend', this.onTrackpadTouchEnd);\n el.addEventListener('triggerdown', this.onTriggerDown);\n el.addEventListener('triggerup', this.onTriggerUp);\n el.addEventListener('triggertouchstart', this.onTriggerTouchStart);\n el.addEventListener('triggertouchend', this.onTriggerTouchEnd);\n el.addEventListener('griptouchstart', this.onGripTouchStart);\n el.addEventListener('griptouchend', this.onGripTouchEnd);\n el.addEventListener('thumbstickdown', this.onThumbstickDown);\n el.addEventListener('thumbstickup', this.onThumbstickUp);\n el.addEventListener('abuttontouchstart', this.onAorXTouchStart);\n el.addEventListener('abuttontouchend', this.onAorXTouchEnd);\n el.addEventListener('bbuttontouchstart', this.onBorYTouchStart);\n el.addEventListener('bbuttontouchend', this.onBorYTouchEnd);\n el.addEventListener('xbuttontouchstart', this.onAorXTouchStart);\n el.addEventListener('xbuttontouchend', this.onAorXTouchEnd);\n el.addEventListener('ybuttontouchstart', this.onBorYTouchStart);\n el.addEventListener('ybuttontouchend', this.onBorYTouchEnd);\n el.addEventListener('surfacetouchstart', this.onSurfaceTouchStart);\n el.addEventListener('surfacetouchend', this.onSurfaceTouchEnd);\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('gripdown', this.onGripDown);\n el.removeEventListener('gripup', this.onGripUp);\n el.removeEventListener('trackpaddown', this.onTrackpadDown);\n el.removeEventListener('trackpadup', this.onTrackpadUp);\n el.removeEventListener('trackpadtouchstart', this.onTrackpadTouchStart);\n el.removeEventListener('trackpadtouchend', this.onTrackpadTouchEnd);\n el.removeEventListener('triggerdown', this.onTriggerDown);\n el.removeEventListener('triggerup', this.onTriggerUp);\n el.removeEventListener('triggertouchstart', this.onTriggerTouchStart);\n el.removeEventListener('triggertouchend', this.onTriggerTouchEnd);\n el.removeEventListener('griptouchstart', this.onGripTouchStart);\n el.removeEventListener('griptouchend', this.onGripTouchEnd);\n el.removeEventListener('thumbstickdown', this.onThumbstickDown);\n el.removeEventListener('thumbstickup', this.onThumbstickUp);\n el.removeEventListener('abuttontouchstart', this.onAorXTouchStart);\n el.removeEventListener('abuttontouchend', this.onAorXTouchEnd);\n el.removeEventListener('bbuttontouchstart', this.onBorYTouchStart);\n el.removeEventListener('bbuttontouchend', this.onBorYTouchEnd);\n el.removeEventListener('xbuttontouchstart', this.onAorXTouchStart);\n el.removeEventListener('xbuttontouchend', this.onAorXTouchEnd);\n el.removeEventListener('ybuttontouchstart', this.onBorYTouchStart);\n el.removeEventListener('ybuttontouchend', this.onBorYTouchEnd);\n el.removeEventListener('surfacetouchstart', this.onSurfaceTouchStart);\n el.removeEventListener('surfacetouchend', this.onSurfaceTouchEnd);\n },\n\n /**\n * Update handler. More like the `init` handler since the only property is the hand, and\n * that won't be changing much.\n */\n update: function (previousHand) {\n var controlConfiguration;\n var el = this.el;\n var hand = this.data.hand;\n var handModelStyle = this.data.handModelStyle;\n var handColor = this.data.color;\n var self = this;\n\n // Get common configuration to abstract different vendor controls.\n controlConfiguration = {\n hand: hand,\n model: false\n };\n\n // Set model.\n if (hand !== previousHand) {\n var handmodelUrl = MODEL_URLS[handModelStyle + hand.charAt(0).toUpperCase() + hand.slice(1)];\n this.loader.load(handmodelUrl, function (gltf) {\n var mesh = gltf.scene.children[0];\n var handModelOrientation = hand === 'left' ? Math.PI / 2 : -Math.PI / 2;\n mesh.mixer = new THREE.AnimationMixer(mesh);\n self.clips = gltf.animations;\n el.setObject3D('mesh', mesh);\n\n var handMaterial = mesh.children[1].material;\n handMaterial.color = new THREE.Color(handColor);\n mesh.position.set(0, 0, 0);\n mesh.rotation.set(0, 0, handModelOrientation);\n el.setAttribute('magicleap-controls', controlConfiguration);\n el.setAttribute('vive-controls', controlConfiguration);\n el.setAttribute('oculus-touch-controls', controlConfiguration);\n el.setAttribute('windows-motion-controls', controlConfiguration);\n });\n }\n },\n\n remove: function () {\n this.el.removeObject3D('mesh');\n },\n\n /**\n * Play model animation, based on which button was pressed and which kind of event.\n *\n * 1. Process buttons.\n * 2. Determine gesture (this.determineGesture()).\n * 3. Animation gesture (this.animationGesture()).\n * 4. Emit gesture events (this.emitGestureEvents()).\n *\n * @param {string} button - Name of the button.\n * @param {string} evt - Type of event for the button (i.e., down/up/touchstart/touchend).\n */\n handleButton: function (button, evt) {\n var lastGesture;\n var isPressed = evt === 'down';\n var isTouched = evt === 'touchstart';\n\n // Update objects.\n if (evt.indexOf('touch') === 0) {\n // Update touch object.\n if (isTouched === this.touchedButtons[button]) { return; }\n this.touchedButtons[button] = isTouched;\n } else {\n // Update button object.\n if (isPressed === this.pressedButtons[button]) { return; }\n this.pressedButtons[button] = isPressed;\n }\n\n // Determine the gesture.\n lastGesture = this.gesture;\n this.gesture = this.determineGesture();\n\n // Same gesture.\n if (this.gesture === lastGesture) { return; }\n // Animate gesture.\n this.animateGesture(this.gesture, lastGesture);\n\n // Emit events.\n this.emitGestureEvents(this.gesture, lastGesture);\n },\n\n /**\n * Determine which pose hand should be in considering active and touched buttons.\n */\n determineGesture: function () {\n var gesture;\n var isGripActive = this.pressedButtons.grip;\n var isSurfaceActive = this.pressedButtons.surface || this.touchedButtons.surface;\n var isTrackpadActive = this.pressedButtons.trackpad || this.touchedButtons.trackpad;\n var isTriggerActive = this.pressedButtons.trigger || this.touchedButtons.trigger;\n var isABXYActive = this.touchedButtons.AorX || this.touchedButtons.BorY;\n var isVive = isViveController(this.el.components['tracked-controls']);\n\n // Works well with Oculus Touch and Windows Motion Controls, but Vive needs tweaks.\n if (isVive) {\n if (isGripActive || isTriggerActive) {\n gesture = ANIMATIONS.fist;\n } else if (isTrackpadActive) {\n gesture = ANIMATIONS.point;\n }\n } else {\n if (isGripActive) {\n if (isSurfaceActive || isABXYActive || isTrackpadActive) {\n gesture = isTriggerActive ? ANIMATIONS.fist : ANIMATIONS.point;\n } else {\n gesture = isTriggerActive ? ANIMATIONS.thumbUp : ANIMATIONS.pointThumb;\n }\n } else if (isTriggerActive) {\n gesture = ANIMATIONS.hold;\n }\n }\n\n return gesture;\n },\n\n /**\n * Play corresponding clip to a gesture\n */\n getClip: function (gesture) {\n var clip;\n var i;\n for (i = 0; i < this.clips.length; i++) {\n clip = this.clips[i];\n if (clip.name !== gesture) { continue; }\n return clip;\n }\n },\n\n /**\n * Play gesture animation.\n *\n * @param {string} gesture - Which pose to animate to. If absent, then animate to open.\n * @param {string} lastGesture - Previous gesture, to reverse back to open if needed.\n */\n animateGesture: function (gesture, lastGesture) {\n if (gesture) {\n this.playAnimation(gesture || ANIMATIONS.open, lastGesture, false);\n return;\n }\n\n // If no gesture, then reverse the current gesture back to open pose.\n this.playAnimation(lastGesture, lastGesture, true);\n },\n\n /**\n * Emit `hand-controls`-specific events.\n */\n emitGestureEvents: function (gesture, lastGesture) {\n var el = this.el;\n var eventName;\n\n if (lastGesture === gesture) { return; }\n\n // Emit event for lastGesture not inactive.\n eventName = getGestureEventName(lastGesture, false);\n if (eventName) { el.emit(eventName); }\n\n // Emit event for current gesture now active.\n eventName = getGestureEventName(gesture, true);\n if (eventName) { el.emit(eventName); }\n },\n\n /**\n * Play hand animation based on button state.\n *\n * @param {string} gesture - Name of the animation as specified by the model.\n * @param {string} lastGesture - Previous pose.\n * @param {boolean} reverse - Whether animation should play in reverse.\n */\n playAnimation: function (gesture, lastGesture, reverse) {\n var clip;\n var fromAction;\n var mesh = this.el.getObject3D('mesh');\n var toAction;\n\n if (!mesh) { return; }\n\n // Stop all current animations.\n mesh.mixer.stopAllAction();\n\n // Grab clip action.\n clip = this.getClip(gesture);\n toAction = mesh.mixer.clipAction(clip);\n toAction.clampWhenFinished = true;\n toAction.loop = THREE.LoopRepeat;\n toAction.repetitions = 0;\n toAction.timeScale = reverse ? -1 : 1;\n toAction.time = reverse ? clip.duration : 0;\n toAction.weight = 1;\n\n // No gesture to gesture or gesture to no gesture.\n if (!lastGesture || gesture === lastGesture) {\n // Stop all current animations.\n mesh.mixer.stopAllAction();\n // Play animation.\n toAction.play();\n return;\n }\n\n // Animate or crossfade from gesture to gesture.\n clip = this.getClip(lastGesture);\n fromAction = mesh.mixer.clipAction(clip);\n fromAction.weight = 0.15;\n fromAction.play();\n toAction.play();\n fromAction.crossFadeTo(toAction, 0.15, true);\n }\n});\n\n/**\n * Suffix gestures based on toggle state (e.g., open/close, up/down, start/end).\n *\n * @param {string} gesture\n * @param {boolean} active\n */\nfunction getGestureEventName (gesture, active) {\n var eventName;\n\n if (!gesture) { return; }\n\n eventName = EVENTS[gesture];\n if (eventName === 'grip') {\n return eventName + (active ? 'close' : 'open');\n }\n if (eventName === 'point') {\n return eventName + (active ? 'up' : 'down');\n }\n if (eventName === 'pointing' || eventName === 'pistol') {\n return eventName + (active ? 'start' : 'end');\n }\n}\n\nfunction isViveController (trackedControls) {\n var controller = trackedControls && trackedControls.controller;\n var isVive = controller && (controller.id && controller.id.indexOf('OpenVR ') === 0 ||\n (controller.profiles &&\n controller.profiles[0] &&\n controller.profiles[0] === 'htc-vive-controller-mv'));\n return isVive;\n}\n", + "require('./animation');\nrequire('./camera');\nrequire('./cursor');\nrequire('./daydream-controls');\nrequire('./gearvr-controls');\nrequire('./geometry');\nrequire('./generic-tracked-controller-controls');\nrequire('./gltf-model');\nrequire('./hand-controls');\nrequire('./laser-controls');\nrequire('./light');\nrequire('./line');\nrequire('./link');\nrequire('./look-controls');\nrequire('./magicleap-controls');\nrequire('./material');\nrequire('./obj-model');\nrequire('./oculus-go-controls');\nrequire('./oculus-touch-controls');\nrequire('./position');\nrequire('./raycaster');\nrequire('./rotation');\nrequire('./scale');\nrequire('./shadow');\nrequire('./sound');\nrequire('./text');\nrequire('./tracked-controls');\nrequire('./tracked-controls-webvr');\nrequire('./tracked-controls-webxr');\nrequire('./visible');\nrequire('./vive-controls');\nrequire('./vive-focus-controls');\nrequire('./wasd-controls');\nrequire('./windows-motion-controls');\n\nrequire('./scene/background');\nrequire('./scene/debug');\nrequire('./scene/device-orientation-permission-ui');\nrequire('./scene/embedded');\nrequire('./scene/inspector');\nrequire('./scene/fog');\nrequire('./scene/keyboard-shortcuts');\nrequire('./scene/pool');\nrequire('./scene/screenshot');\nrequire('./scene/stats');\nrequire('./scene/vr-mode-ui');\n", + "var registerComponent = require('../core/component').registerComponent;\nvar utils = require('../utils/');\n\nregisterComponent('laser-controls', {\n schema: {\n hand: {default: 'right'},\n model: {default: true},\n defaultModelColor: {type: 'color', default: 'grey'}\n },\n\n init: function () {\n var config = this.config;\n var data = this.data;\n var el = this.el;\n var self = this;\n var controlsConfiguration = {hand: data.hand, model: data.model};\n\n // Set all controller models.\n el.setAttribute('daydream-controls', controlsConfiguration);\n el.setAttribute('gearvr-controls', controlsConfiguration);\n el.setAttribute('magicleap-controls', controlsConfiguration);\n el.setAttribute('oculus-go-controls', controlsConfiguration);\n el.setAttribute('oculus-touch-controls', controlsConfiguration);\n el.setAttribute('vive-controls', controlsConfiguration);\n el.setAttribute('vive-focus-controls', controlsConfiguration);\n el.setAttribute('windows-motion-controls', controlsConfiguration);\n el.setAttribute('generic-tracked-controller-controls', controlsConfiguration);\n\n // Wait for controller to connect, or have a valid pointing pose, before creating ray\n el.addEventListener('controllerconnected', createRay);\n el.addEventListener('controllerdisconnected', hideRay);\n el.addEventListener('controllermodelready', function (evt) {\n createRay(evt);\n self.modelReady = true;\n });\n\n function createRay (evt) {\n var controllerConfig = config[evt.detail.name];\n\n if (!controllerConfig) { return; }\n\n // Show the line unless a particular config opts to hide it, until a controllermodelready\n // event comes through.\n var raycasterConfig = utils.extend({\n showLine: true\n }, controllerConfig.raycaster || {});\n\n // The controllermodelready event contains a rayOrigin that takes into account\n // offsets specific to the loaded model.\n if (evt.detail.rayOrigin) {\n raycasterConfig.origin = evt.detail.rayOrigin.origin;\n raycasterConfig.direction = evt.detail.rayOrigin.direction;\n raycasterConfig.showLine = true;\n }\n\n // Only apply a default raycaster if it does not yet exist. This prevents it overwriting\n // config applied from a controllermodelready event.\n if (evt.detail.rayOrigin || !self.modelReady) {\n el.setAttribute('raycaster', raycasterConfig);\n } else {\n el.setAttribute('raycaster', 'showLine', true);\n }\n\n el.setAttribute('cursor', utils.extend({\n fuse: false\n }, controllerConfig.cursor));\n }\n\n function hideRay () {\n el.setAttribute('raycaster', 'showLine', false);\n }\n },\n\n config: {\n 'daydream-controls': {\n cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']}\n },\n\n 'gearvr-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0.0010, z: 0}}\n },\n\n 'generic-tracked-controller-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']}\n },\n\n 'magicleap-controls': {\n cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']}\n },\n\n 'oculus-go-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0.0005, z: 0}}\n },\n\n 'oculus-touch-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {origin: {x: 0, y: 0, z: 0}}\n },\n\n 'vive-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']}\n },\n\n 'vive-focus-controls': {\n cursor: {downEvents: ['trackpaddown', 'triggerdown'], upEvents: ['trackpadup', 'triggerup']}\n },\n\n 'windows-motion-controls': {\n cursor: {downEvents: ['triggerdown'], upEvents: ['triggerup']},\n raycaster: {showLine: false}\n }\n }\n});\n", "var bind = require('../utils/bind');\nvar diff = require('../utils').diff;\nvar debug = require('../utils/debug');\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\n\nvar degToRad = THREE.Math.degToRad;\nvar warn = debug('components:light:warn');\n\n/**\n * Light component.\n */\nmodule.exports.Component = registerComponent('light', {\n schema: {\n angle: {default: 60, if: {type: ['spot']}},\n color: {type: 'color'},\n groundColor: {type: 'color', if: {type: ['hemisphere']}},\n decay: {default: 1, if: {type: ['point', 'spot']}},\n distance: {default: 0.0, min: 0, if: {type: ['point', 'spot']}},\n intensity: {default: 1.0, min: 0, if: {type: ['ambient', 'directional', 'hemisphere', 'point', 'spot']}},\n penumbra: {default: 0, min: 0, max: 1, if: {type: ['spot']}},\n type: {\n default: 'directional',\n oneOf: ['ambient', 'directional', 'hemisphere', 'point', 'spot'],\n schemaChange: true\n },\n target: {type: 'selector', if: {type: ['spot', 'directional']}},\n\n // Shadows.\n castShadow: {default: false, if: {type: ['point', 'spot', 'directional']}},\n shadowBias: {default: 0, if: {castShadow: true}},\n shadowCameraFar: {default: 500, if: {castShadow: true}},\n shadowCameraFov: {default: 90, if: {castShadow: true}},\n shadowCameraNear: {default: 0.5, if: {castShadow: true}},\n shadowCameraTop: {default: 5, if: {castShadow: true}},\n shadowCameraRight: {default: 5, if: {castShadow: true}},\n shadowCameraBottom: {default: -5, if: {castShadow: true}},\n shadowCameraLeft: {default: -5, if: {castShadow: true}},\n shadowCameraVisible: {default: false, if: {castShadow: true}},\n shadowMapHeight: {default: 512, if: {castShadow: true}},\n shadowMapWidth: {default: 512, if: {castShadow: true}},\n shadowRadius: {default: 1, if: {castShadow: true}}\n },\n\n /**\n * Notifies scene a light has been added to remove default lighting.\n */\n init: function () {\n var el = this.el;\n this.light = null;\n this.defaultTarget = null;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.system.registerLight(el);\n },\n\n /**\n * (Re)create or update light.\n */\n update: function (oldData) {\n var data = this.data;\n var diffData = diff(data, oldData);\n var light = this.light;\n var rendererSystem = this.rendererSystem;\n var self = this;\n\n // Existing light.\n if (light && !('type' in diffData)) {\n var shadowsLoaded = false;\n // Light type has not changed. Update light.\n Object.keys(diffData).forEach(function (key) {\n var value = data[key];\n\n switch (key) {\n case 'color': {\n light.color.set(value);\n rendererSystem.applyColorCorrection(light.color);\n break;\n }\n\n case 'groundColor': {\n light.groundColor.set(value);\n rendererSystem.applyColorCorrection(light.groundColor);\n break;\n }\n\n case 'angle': {\n light.angle = degToRad(value);\n break;\n }\n\n case 'target': {\n // Reset target if selector is null.\n if (value === null) {\n if (data.type === 'spot' || data.type === 'directional') {\n light.target = self.defaultTarget;\n }\n } else {\n // Target specified, set target to entity's `object3D` when it is loaded.\n if (value.hasLoaded) {\n self.onSetTarget(value, light);\n } else {\n value.addEventListener('loaded', bind(self.onSetTarget, self, value, light));\n }\n }\n break;\n }\n\n case 'castShadow':\n case 'shadowBias':\n case 'shadowCameraFar':\n case 'shadowCameraFov':\n case 'shadowCameraNear':\n case 'shadowCameraTop':\n case 'shadowCameraRight':\n case 'shadowCameraBottom':\n case 'shadowCameraLeft':\n case 'shadowCameraVisible':\n case 'shadowMapHeight':\n case 'shadowMapWidth':\n case 'shadowRadius':\n if (!shadowsLoaded) {\n self.updateShadow();\n shadowsLoaded = true;\n }\n break;\n\n default: {\n light[key] = value;\n }\n }\n });\n return;\n }\n\n // No light yet or light type has changed. Create and add light.\n this.setLight(this.data);\n this.updateShadow();\n },\n\n setLight: function (data) {\n var el = this.el;\n var newLight = this.getLight(data);\n if (newLight) {\n if (this.light) {\n el.removeObject3D('light');\n }\n\n this.light = newLight;\n this.light.el = el;\n el.setObject3D('light', this.light);\n\n // HACK solution for issue #1624\n if (data.type === 'spot' || data.type === 'directional' || data.type === 'hemisphere') {\n el.getObject3D('light').translateY(-1);\n }\n\n // set and position default lighttarget as a child to enable spotlight orientation\n if (data.type === 'spot') {\n el.setObject3D('light-target', this.defaultTarget);\n el.getObject3D('light-target').position.set(0, 0, -1);\n }\n }\n },\n\n /**\n * Updates shadow-related properties on the current light.\n */\n updateShadow: function () {\n var el = this.el;\n var data = this.data;\n var light = this.light;\n\n light.castShadow = data.castShadow;\n\n // Shadow camera helper.\n var cameraHelper = el.getObject3D('cameraHelper');\n if (data.shadowCameraVisible && !cameraHelper) {\n el.setObject3D('cameraHelper', new THREE.CameraHelper(light.shadow.camera));\n } else if (!data.shadowCameraVisible && cameraHelper) {\n el.removeObject3D('cameraHelper');\n }\n\n if (!data.castShadow) { return light; }\n\n // Shadow appearance.\n light.shadow.bias = data.shadowBias;\n light.shadow.radius = data.shadowRadius;\n light.shadow.mapSize.height = data.shadowMapHeight;\n light.shadow.mapSize.width = data.shadowMapWidth;\n\n // Shadow camera.\n light.shadow.camera.near = data.shadowCameraNear;\n light.shadow.camera.far = data.shadowCameraFar;\n if (light.shadow.camera instanceof THREE.OrthographicCamera) {\n light.shadow.camera.top = data.shadowCameraTop;\n light.shadow.camera.right = data.shadowCameraRight;\n light.shadow.camera.bottom = data.shadowCameraBottom;\n light.shadow.camera.left = data.shadowCameraLeft;\n } else {\n light.shadow.camera.fov = data.shadowCameraFov;\n }\n light.shadow.camera.updateProjectionMatrix();\n\n if (cameraHelper) { cameraHelper.update(); }\n },\n\n /**\n * Creates a new three.js light object given data object defining the light.\n *\n * @param {object} data\n */\n getLight: function (data) {\n var angle = data.angle;\n var color = new THREE.Color(data.color);\n this.rendererSystem.applyColorCorrection(color);\n color = color.getHex();\n var decay = data.decay;\n var distance = data.distance;\n var groundColor = new THREE.Color(data.groundColor);\n this.rendererSystem.applyColorCorrection(groundColor);\n groundColor = groundColor.getHex();\n var intensity = data.intensity;\n var type = data.type;\n var target = data.target;\n var light = null;\n\n switch (type.toLowerCase()) {\n case 'ambient': {\n return new THREE.AmbientLight(color, intensity);\n }\n\n case 'directional': {\n light = new THREE.DirectionalLight(color, intensity);\n this.defaultTarget = light.target;\n if (target) {\n if (target.hasLoaded) {\n this.onSetTarget(target, light);\n } else {\n target.addEventListener('loaded', bind(this.onSetTarget, this, target, light));\n }\n }\n return light;\n }\n\n case 'hemisphere': {\n return new THREE.HemisphereLight(color, groundColor, intensity);\n }\n\n case 'point': {\n return new THREE.PointLight(color, intensity, distance, decay);\n }\n\n case 'spot': {\n light = new THREE.SpotLight(color, intensity, distance, degToRad(angle), data.penumbra, decay);\n this.defaultTarget = light.target;\n if (target) {\n if (target.hasLoaded) {\n this.onSetTarget(target, light);\n } else {\n target.addEventListener('loaded', bind(this.onSetTarget, this, target, light));\n }\n }\n return light;\n }\n\n default: {\n warn('%s is not a valid light type. ' +\n 'Choose from ambient, directional, hemisphere, point, spot.', type);\n }\n }\n },\n\n onSetTarget: function (targetEl, light) {\n light.target = targetEl.object3D;\n },\n\n /**\n * Remove light on remove (callback).\n */\n remove: function () {\n var el = this.el;\n el.removeObject3D('light');\n if (el.getObject3D('cameraHelper')) {\n el.removeObject3D('cameraHelper');\n }\n }\n});\n", - "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\n\nmodule.exports.Component = registerComponent('line', {\n schema: {\n start: {type: 'vec3', default: {x: 0, y: 0, z: 0}},\n end: {type: 'vec3', default: {x: 0, y: 0, z: 0}},\n color: {type: 'color', default: '#74BEC1'},\n opacity: {type: 'number', default: 1},\n visible: {default: true}\n },\n\n multiple: true,\n\n init: function () {\n var data = this.data;\n var geometry;\n var material;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n material = this.material = new THREE.LineBasicMaterial({\n color: data.color,\n opacity: data.opacity,\n transparent: data.opacity < 1,\n visible: data.visible\n });\n geometry = this.geometry = new THREE.BufferGeometry();\n geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3));\n\n this.rendererSystem.applyColorCorrection(material.color);\n this.line = new THREE.Line(geometry, material);\n this.el.setObject3D(this.attrName, this.line);\n },\n\n update: function (oldData) {\n var data = this.data;\n var geometry = this.geometry;\n var geoNeedsUpdate = false;\n var material = this.material;\n var positionArray = geometry.attributes.position.array;\n\n // Update geometry.\n if (!isEqualVec3(data.start, oldData.start)) {\n positionArray[0] = data.start.x;\n positionArray[1] = data.start.y;\n positionArray[2] = data.start.z;\n geoNeedsUpdate = true;\n }\n\n if (!isEqualVec3(data.end, oldData.end)) {\n positionArray[3] = data.end.x;\n positionArray[4] = data.end.y;\n positionArray[5] = data.end.z;\n geoNeedsUpdate = true;\n }\n\n if (geoNeedsUpdate) {\n geometry.attributes.position.needsUpdate = true;\n geometry.computeBoundingSphere();\n }\n\n material.color.setStyle(data.color);\n this.rendererSystem.applyColorCorrection(material.color);\n material.opacity = data.opacity;\n material.transparent = data.opacity < 1;\n material.visible = data.visible;\n },\n\n remove: function () {\n this.el.removeObject3D('line', this.line);\n }\n});\n\nfunction isEqualVec3 (a, b) {\n if (!a || !b) { return false; }\n return (a.x === b.x && a.y === b.y && a.z === b.z);\n}\n", + "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\n\nmodule.exports.Component = registerComponent('line', {\n schema: {\n start: {type: 'vec3', default: {x: 0, y: 0, z: 0}},\n end: {type: 'vec3', default: {x: 0, y: 0, z: 0}},\n color: {type: 'color', default: '#74BEC1'},\n opacity: {type: 'number', default: 1},\n visible: {default: true}\n },\n\n multiple: true,\n\n init: function () {\n var data = this.data;\n var geometry;\n var material;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n material = this.material = new THREE.LineBasicMaterial({\n color: data.color,\n opacity: data.opacity,\n transparent: data.opacity < 1,\n visible: data.visible\n });\n geometry = this.geometry = new THREE.BufferGeometry();\n geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(2 * 3), 3));\n\n this.rendererSystem.applyColorCorrection(material.color);\n this.line = new THREE.Line(geometry, material);\n this.el.setObject3D(this.attrName, this.line);\n },\n\n update: function (oldData) {\n var data = this.data;\n var geometry = this.geometry;\n var geoNeedsUpdate = false;\n var material = this.material;\n var positionArray = geometry.attributes.position.array;\n\n // Update geometry.\n if (!isEqualVec3(data.start, oldData.start)) {\n positionArray[0] = data.start.x;\n positionArray[1] = data.start.y;\n positionArray[2] = data.start.z;\n geoNeedsUpdate = true;\n }\n\n if (!isEqualVec3(data.end, oldData.end)) {\n positionArray[3] = data.end.x;\n positionArray[4] = data.end.y;\n positionArray[5] = data.end.z;\n geoNeedsUpdate = true;\n }\n\n if (geoNeedsUpdate) {\n geometry.attributes.position.needsUpdate = true;\n geometry.computeBoundingSphere();\n }\n\n material.color.setStyle(data.color);\n this.rendererSystem.applyColorCorrection(material.color);\n material.opacity = data.opacity;\n material.transparent = data.opacity < 1;\n material.visible = data.visible;\n },\n\n remove: function () {\n this.el.removeObject3D('line', this.line);\n }\n});\n\nfunction isEqualVec3 (a, b) {\n if (!a || !b) { return false; }\n return (a.x === b.x && a.y === b.y && a.z === b.z);\n}\n", "var registerComponent = require('../core/component').registerComponent;\nvar registerShader = require('../core/shader').registerShader;\nvar THREE = require('../lib/three');\n\n/**\n * Link component. Connect experiences and traverse between them in VR\n *\n * @member {object} hiddenEls - Store the hidden elements during peek mode.\n */\nmodule.exports.Component = registerComponent('link', {\n schema: {\n backgroundColor: {default: 'red', type: 'color'},\n borderColor: {default: 'white', type: 'color'},\n highlighted: {default: false},\n highlightedColor: {default: '#24CAFF', type: 'color'},\n href: {default: ''},\n image: {type: 'asset'},\n on: {default: 'click'},\n peekMode: {default: false},\n title: {default: ''},\n titleColor: {default: 'white', type: 'color'},\n visualAspectEnabled: {default: false}\n },\n\n init: function () {\n this.navigate = this.navigate.bind(this);\n this.previousQuaternion = undefined;\n this.quaternionClone = new THREE.Quaternion();\n // Store hidden elements during peek mode so we can show them again later.\n this.hiddenEls = [];\n },\n\n update: function (oldData) {\n var data = this.data;\n var el = this.el;\n var backgroundColor;\n var strokeColor;\n\n if (!data.visualAspectEnabled) { return; }\n\n this.initVisualAspect();\n\n backgroundColor = data.highlighted ? data.highlightedColor : data.backgroundColor;\n strokeColor = data.highlighted ? data.highlightedColor : data.borderColor;\n el.setAttribute('material', 'backgroundColor', backgroundColor);\n el.setAttribute('material', 'strokeColor', strokeColor);\n\n if (data.on !== oldData.on) { this.updateEventListener(); }\n\n if (oldData.peekMode !== undefined &&\n data.peekMode !== oldData.peekMode) { this.updatePeekMode(); }\n\n if (!data.image || oldData.image === data.image) { return; }\n\n el.setAttribute('material', 'pano',\n typeof data.image === 'string' ? data.image : data.image.src);\n },\n\n /*\n * Toggle all elements and full 360 preview of the linked page.\n */\n updatePeekMode: function () {\n var el = this.el;\n var sphereEl = this.sphereEl;\n if (this.data.peekMode) {\n this.hideAll();\n el.getObject3D('mesh').visible = false;\n sphereEl.setAttribute('visible', true);\n } else {\n this.showAll();\n el.getObject3D('mesh').visible = true;\n sphereEl.setAttribute('visible', false);\n }\n },\n\n play: function () {\n this.updateEventListener();\n },\n\n pause: function () {\n this.removeEventListener();\n },\n\n updateEventListener: function () {\n var el = this.el;\n if (!el.isPlaying) { return; }\n this.removeEventListener();\n el.addEventListener(this.data.on, this.navigate);\n },\n\n removeEventListener: function () {\n var on = this.data.on;\n if (!on) { return; }\n this.el.removeEventListener(on, this.navigate);\n },\n\n initVisualAspect: function () {\n var el = this.el;\n var semiSphereEl;\n var sphereEl;\n var textEl;\n\n if (!this.data.visualAspectEnabled || this.visualAspectInitialized) { return; }\n\n textEl = this.textEl = this.textEl || document.createElement('a-entity');\n sphereEl = this.sphereEl = this.sphereEl || document.createElement('a-entity');\n semiSphereEl = this.semiSphereEl = this.semiSphereEl || document.createElement('a-entity');\n\n // Set portal.\n el.setAttribute('geometry', {primitive: 'circle', radius: 1.0, segments: 64});\n el.setAttribute('material', {shader: 'portal', pano: this.data.image, side: 'double'});\n\n // Set text that displays the link title and URL.\n textEl.setAttribute('text', {\n color: this.data.titleColor,\n align: 'center',\n font: 'kelsonsans',\n value: this.data.title || this.data.href,\n width: 4\n });\n textEl.setAttribute('position', '0 1.5 0');\n el.appendChild(textEl);\n\n // Set sphere rendered when camera is close to portal to allow user to peek inside.\n semiSphereEl.setAttribute('geometry', {\n primitive: 'sphere',\n radius: 1.0,\n phiStart: 0,\n segmentsWidth: 64,\n segmentsHeight: 64,\n phiLength: 180,\n thetaStart: 0,\n thetaLength: 360\n });\n semiSphereEl.setAttribute('material', {\n shader: 'portal',\n borderEnabled: 0.0,\n pano: this.data.image,\n side: 'back'\n });\n semiSphereEl.setAttribute('rotation', '0 180 0');\n semiSphereEl.setAttribute('position', '0 0 0');\n semiSphereEl.setAttribute('visible', false);\n el.appendChild(semiSphereEl);\n\n // Set sphere rendered when camera is close to portal to allow user to peek inside.\n sphereEl.setAttribute('geometry', {\n primitive: 'sphere',\n radius: 10,\n segmentsWidth: 64,\n segmentsHeight: 64\n });\n sphereEl.setAttribute('material', {\n shader: 'portal',\n borderEnabled: 0.0,\n pano: this.data.image,\n side: 'back'\n });\n sphereEl.setAttribute('visible', false);\n el.appendChild(sphereEl);\n\n this.visualAspectInitialized = true;\n },\n\n navigate: function () {\n window.location = this.data.href;\n },\n\n /**\n * 1. Swap plane that represents portal with sphere with a hole when the camera is close\n * so user can peek inside portal. Sphere is rendered on oposite side of portal\n * from where user enters.\n * 2. Place the url/title above or inside portal depending on distance to camera.\n * 3. Face portal to camera when far away from user.\n */\n tick: (function () {\n var cameraWorldPosition = new THREE.Vector3();\n var elWorldPosition = new THREE.Vector3();\n var quaternion = new THREE.Quaternion();\n var scale = new THREE.Vector3();\n\n return function () {\n var el = this.el;\n var object3D = el.object3D;\n var camera = el.sceneEl.camera;\n var cameraPortalOrientation;\n var distance;\n var textEl = this.textEl;\n\n if (!this.data.visualAspectEnabled) { return; }\n\n // Update matrices\n object3D.updateMatrixWorld();\n camera.parent.updateMatrixWorld();\n camera.updateMatrixWorld();\n\n object3D.matrix.decompose(elWorldPosition, quaternion, scale);\n elWorldPosition.setFromMatrixPosition(object3D.matrixWorld);\n cameraWorldPosition.setFromMatrixPosition(camera.matrixWorld);\n distance = elWorldPosition.distanceTo(cameraWorldPosition);\n\n if (distance > 20) {\n // Store original orientation to be restored when the portal stops facing the camera.\n if (!this.previousQuaternion) {\n this.quaternionClone.copy(quaternion);\n this.previousQuaternion = this.quaternionClone;\n }\n // If the portal is far away from the user, face portal to camera.\n object3D.lookAt(cameraWorldPosition);\n } else {\n // When portal is close to the user/camera.\n cameraPortalOrientation = this.calculateCameraPortalOrientation();\n // If user gets very close to portal, replace with holed sphere they can peek in.\n if (distance < 0.5) {\n // Configure text size and sphere orientation depending side user approaches portal.\n if (this.semiSphereEl.getAttribute('visible') === true) { return; }\n textEl.setAttribute('text', 'width', 1.5);\n if (cameraPortalOrientation <= 0.0) {\n textEl.setAttribute('position', '0 0 0.75');\n textEl.setAttribute('rotation', '0 180 0');\n this.semiSphereEl.setAttribute('rotation', '0 0 0');\n } else {\n textEl.setAttribute('position', '0 0 -0.75');\n textEl.setAttribute('rotation', '0 0 0');\n this.semiSphereEl.setAttribute('rotation', '0 180 0');\n }\n el.getObject3D('mesh').visible = false;\n this.semiSphereEl.setAttribute('visible', true);\n this.peekCameraPortalOrientation = cameraPortalOrientation;\n } else {\n // Calculate wich side the camera is approaching the camera (back / front).\n // Adjust text orientation based on camera position.\n if (cameraPortalOrientation <= 0.0) {\n textEl.setAttribute('rotation', '0 180 0');\n } else {\n textEl.setAttribute('rotation', '0 0 0');\n }\n textEl.setAttribute('text', 'width', 5);\n textEl.setAttribute('position', '0 1.5 0');\n el.getObject3D('mesh').visible = true;\n this.semiSphereEl.setAttribute('visible', false);\n this.peekCameraPortalOrientation = undefined;\n }\n if (this.previousQuaternion) {\n object3D.quaternion.copy(this.previousQuaternion);\n this.previousQuaternion = undefined;\n }\n }\n };\n })(),\n\n hideAll: function () {\n var el = this.el;\n var hiddenEls = this.hiddenEls;\n var self = this;\n if (hiddenEls.length > 0) { return; }\n el.sceneEl.object3D.traverse(function (object) {\n if (object && object.el && object.el.hasAttribute('link-controls')) { return; }\n if (!object.el || object === el.sceneEl.object3D || object.el === el ||\n object.el === self.sphereEl || object.el === el.sceneEl.cameraEl ||\n object.el.getAttribute('visible') === false || object.el === self.textEl ||\n object.el === self.semiSphereEl) {\n return;\n }\n object.el.setAttribute('visible', false);\n hiddenEls.push(object.el);\n });\n },\n\n showAll: function () {\n this.hiddenEls.forEach(function (el) { el.setAttribute('visible', true); });\n this.hiddenEls = [];\n },\n\n /**\n * Calculate whether the camera faces the front or back face of the portal.\n * @returns {number} > 0 if camera faces front of portal, < 0 if it faces back of portal.\n */\n calculateCameraPortalOrientation: (function () {\n var mat4 = new THREE.Matrix4();\n var cameraPosition = new THREE.Vector3();\n var portalNormal = new THREE.Vector3(0, 0, 1);\n var portalPosition = new THREE.Vector3(0, 0, 0);\n\n return function () {\n var el = this.el;\n var camera = el.sceneEl.camera;\n\n // Reset tmp variables.\n cameraPosition.set(0, 0, 0);\n portalNormal.set(0, 0, 1);\n portalPosition.set(0, 0, 0);\n\n // Apply portal orientation to the normal.\n el.object3D.matrixWorld.extractRotation(mat4);\n portalNormal.applyMatrix4(mat4);\n\n // Calculate portal world position.\n el.object3D.updateMatrixWorld();\n el.object3D.localToWorld(portalPosition);\n\n // Calculate camera world position.\n camera.parent.parent.updateMatrixWorld();\n camera.parent.updateMatrixWorld();\n camera.updateMatrixWorld();\n camera.localToWorld(cameraPosition);\n\n // Calculate vector from portal to camera.\n // (portal) -------> (camera)\n cameraPosition.sub(portalPosition).normalize();\n portalNormal.normalize();\n\n // Side where camera approaches portal is given by sign of dot product of portal normal\n // and portal to camera vectors.\n return Math.sign(portalNormal.dot(cameraPosition));\n };\n })(),\n\n remove: function () {\n this.removeEventListener();\n }\n});\n\n/* eslint-disable */\nregisterShader('portal', {\n schema: {\n borderEnabled: {default: 1.0, type: 'int', is: 'uniform'},\n backgroundColor: {default: 'red', type: 'color', is: 'uniform'},\n pano: {type: 'map', is: 'uniform'},\n strokeColor: {default: 'white', type: 'color', is: 'uniform'}\n },\n\n vertexShader: [\n 'vec3 portalPosition;',\n 'varying vec3 vWorldPosition;',\n 'varying float vDistanceToCenter;',\n 'varying float vDistance;',\n 'void main() {',\n 'vDistanceToCenter = clamp(length(position - vec3(0.0, 0.0, 0.0)), 0.0, 1.0);',\n 'portalPosition = (modelMatrix * vec4(0.0, 0.0, 0.0, 1.0)).xyz;',\n 'vDistance = length(portalPosition - cameraPosition);',\n 'vWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;',\n 'gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',\n '}'\n ].join('\\n'),\n\n fragmentShader: [\n '#define RECIPROCAL_PI2 0.15915494',\n 'uniform sampler2D pano;',\n 'uniform vec3 strokeColor;',\n 'uniform vec3 backgroundColor;',\n 'uniform float borderEnabled;',\n 'varying float vDistanceToCenter;',\n 'varying float vDistance;',\n 'varying vec3 vWorldPosition;',\n 'void main() {',\n 'vec3 direction = normalize(vWorldPosition - cameraPosition);',\n 'vec2 sampleUV;',\n 'float borderThickness = clamp(exp(-vDistance / 50.0), 0.6, 0.95);',\n 'sampleUV.y = saturate(direction.y * 0.5 + 0.5);',\n 'sampleUV.x = atan(direction.z, -direction.x) * -RECIPROCAL_PI2 + 0.5;',\n 'if (vDistanceToCenter > borderThickness && borderEnabled == 1.0) {',\n 'gl_FragColor = vec4(strokeColor, 1.0);',\n '} else {',\n 'gl_FragColor = mix(texture2D(pano, sampleUV), vec4(backgroundColor, 1.0), clamp(pow((vDistance / 15.0), 2.0), 0.0, 1.0));',\n '}',\n '}'\n ].join('\\n')\n});\n/* eslint-enable */\n", - "/* global DeviceOrientationEvent */\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\nvar bind = utils.bind;\n\n// To avoid recalculation at every mouse movement tick\nvar PI_2 = Math.PI / 2;\n\n/**\n * look-controls. Update entity pose, factoring mouse, touch, and WebVR API data.\n */\nmodule.exports.Component = registerComponent('look-controls', {\n dependencies: ['position', 'rotation'],\n\n schema: {\n enabled: {default: true},\n hmdEnabled: {default: true},\n pointerLockEnabled: {default: false},\n reverseMouseDrag: {default: false},\n reverseTouchDrag: {default: false},\n touchEnabled: {default: true}\n },\n\n init: function () {\n this.deltaYaw = 0;\n this.previousHMDPosition = new THREE.Vector3();\n this.hmdQuaternion = new THREE.Quaternion();\n this.magicWindowAbsoluteEuler = new THREE.Euler();\n this.magicWindowDeltaEuler = new THREE.Euler();\n this.position = new THREE.Vector3();\n // To save / restore camera pose\n this.savedRotation = new THREE.Vector3();\n this.savedPosition = new THREE.Vector3();\n this.magicWindowObject = new THREE.Object3D();\n this.rotation = {};\n this.deltaRotation = {};\n this.savedPose = null;\n this.pointerLocked = false;\n this.setupMouseControls();\n this.bindMethods();\n this.el.object3D.matrixAutoUpdate = false;\n this.el.object3D.updateMatrix();\n\n this.setupMagicWindowControls();\n\n this.savedPose = {\n position: new THREE.Vector3(),\n rotation: new THREE.Euler()\n };\n\n // Call enter VR handler if the scene has entered VR before the event listeners attached.\n if (this.el.sceneEl.is('vr-mode')) { this.onEnterVR(); }\n },\n\n setupMagicWindowControls: function () {\n var magicWindowControls;\n\n // Only on mobile devices and only enabled if DeviceOrientation permission has been granted.\n if (utils.device.isMobile()) {\n magicWindowControls = this.magicWindowControls = new THREE.DeviceOrientationControls(this.magicWindowObject);\n if (typeof DeviceOrientationEvent !== 'undefined' && DeviceOrientationEvent.requestPermission) {\n magicWindowControls.enabled = false;\n if (this.el.sceneEl.components['device-orientation-permission-ui'].permissionGranted) {\n magicWindowControls.enabled = true;\n } else {\n this.el.sceneEl.addEventListener('deviceorientationpermissiongranted', function () {\n magicWindowControls.enabled = true;\n });\n }\n }\n }\n },\n\n update: function (oldData) {\n var data = this.data;\n\n // Disable grab cursor classes if no longer enabled.\n if (data.enabled !== oldData.enabled) {\n this.updateGrabCursor(data.enabled);\n }\n\n // Reset pitch and yaw if disabling HMD.\n if (oldData && !data.hmdEnabled && !oldData.hmdEnabled) {\n this.pitchObject.rotation.set(0, 0, 0);\n this.yawObject.rotation.set(0, 0, 0);\n }\n\n if (oldData && !data.pointerLockEnabled !== oldData.pointerLockEnabled) {\n this.removeEventListeners();\n this.addEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n }\n },\n\n tick: function (t) {\n var data = this.data;\n if (!data.enabled) { return; }\n this.updateOrientation();\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n },\n\n remove: function () {\n this.removeEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n },\n\n bindMethods: function () {\n this.onMouseDown = bind(this.onMouseDown, this);\n this.onMouseMove = bind(this.onMouseMove, this);\n this.onMouseUp = bind(this.onMouseUp, this);\n this.onTouchStart = bind(this.onTouchStart, this);\n this.onTouchMove = bind(this.onTouchMove, this);\n this.onTouchEnd = bind(this.onTouchEnd, this);\n this.onEnterVR = bind(this.onEnterVR, this);\n this.onExitVR = bind(this.onExitVR, this);\n this.onPointerLockChange = bind(this.onPointerLockChange, this);\n this.onPointerLockError = bind(this.onPointerLockError, this);\n },\n\n /**\n * Set up states and Object3Ds needed to store rotation data.\n */\n setupMouseControls: function () {\n this.mouseDown = false;\n this.pitchObject = new THREE.Object3D();\n this.yawObject = new THREE.Object3D();\n this.yawObject.position.y = 10;\n this.yawObject.add(this.pitchObject);\n },\n\n /**\n * Add mouse and touch event listeners to canvas.\n */\n addEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n var canvasEl = sceneEl.canvas;\n\n // Wait for canvas to load.\n if (!canvasEl) {\n sceneEl.addEventListener('render-target-loaded', bind(this.addEventListeners, this));\n return;\n }\n\n // Mouse events.\n canvasEl.addEventListener('mousedown', this.onMouseDown, false);\n window.addEventListener('mousemove', this.onMouseMove, false);\n window.addEventListener('mouseup', this.onMouseUp, false);\n\n // Touch events.\n canvasEl.addEventListener('touchstart', this.onTouchStart);\n window.addEventListener('touchmove', this.onTouchMove);\n window.addEventListener('touchend', this.onTouchEnd);\n\n // sceneEl events.\n sceneEl.addEventListener('enter-vr', this.onEnterVR);\n sceneEl.addEventListener('exit-vr', this.onExitVR);\n\n // Pointer Lock events.\n if (this.data.pointerLockEnabled) {\n document.addEventListener('pointerlockchange', this.onPointerLockChange, false);\n document.addEventListener('mozpointerlockchange', this.onPointerLockChange, false);\n document.addEventListener('pointerlockerror', this.onPointerLockError, false);\n }\n },\n\n /**\n * Remove mouse and touch event listeners from canvas.\n */\n removeEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n var canvasEl = sceneEl && sceneEl.canvas;\n\n if (!canvasEl) { return; }\n\n // Mouse events.\n canvasEl.removeEventListener('mousedown', this.onMouseDown);\n window.removeEventListener('mousemove', this.onMouseMove);\n window.removeEventListener('mouseup', this.onMouseUp);\n\n // Touch events.\n canvasEl.removeEventListener('touchstart', this.onTouchStart);\n window.removeEventListener('touchmove', this.onTouchMove);\n window.removeEventListener('touchend', this.onTouchEnd);\n\n // sceneEl events.\n sceneEl.removeEventListener('enter-vr', this.onEnterVR);\n sceneEl.removeEventListener('exit-vr', this.onExitVR);\n\n // Pointer Lock events.\n document.removeEventListener('pointerlockchange', this.onPointerLockChange, false);\n document.removeEventListener('mozpointerlockchange', this.onPointerLockChange, false);\n document.removeEventListener('pointerlockerror', this.onPointerLockError, false);\n },\n\n /**\n * Update orientation for mobile, mouse drag, and headset.\n * Mouse-drag only enabled if HMD is not active.\n */\n updateOrientation: (function () {\n var poseMatrix = new THREE.Matrix4();\n\n return function () {\n var object3D = this.el.object3D;\n var pitchObject = this.pitchObject;\n var yawObject = this.yawObject;\n var pose;\n var sceneEl = this.el.sceneEl;\n\n // In VR mode, THREE is in charge of updating the camera pose.\n if (sceneEl.is('vr-mode') && sceneEl.checkHeadsetConnected()) {\n // With WebXR THREE applies headset pose to the object3D matrixWorld internally.\n // Reflect values back on position, rotation, scale for getAttribute to return the expected values.\n if (sceneEl.hasWebXR) {\n pose = sceneEl.renderer.xr.getCameraPose();\n if (pose) {\n poseMatrix.elements = pose.transform.matrix;\n poseMatrix.decompose(object3D.position, object3D.rotation, object3D.scale);\n }\n }\n return;\n } else {\n object3D.updateMatrix();\n }\n\n this.updateMagicWindowOrientation();\n\n // On mobile, do camera rotation with touch events and sensors.\n object3D.rotation.x = this.magicWindowDeltaEuler.x + pitchObject.rotation.x;\n object3D.rotation.y = this.magicWindowDeltaEuler.y + yawObject.rotation.y;\n object3D.rotation.z = this.magicWindowDeltaEuler.z;\n };\n })(),\n\n updateMagicWindowOrientation: function () {\n var magicWindowAbsoluteEuler = this.magicWindowAbsoluteEuler;\n var magicWindowDeltaEuler = this.magicWindowDeltaEuler;\n // Calculate magic window HMD quaternion.\n if (this.magicWindowControls && this.magicWindowControls.enabled) {\n this.magicWindowControls.update();\n magicWindowAbsoluteEuler.setFromQuaternion(this.magicWindowObject.quaternion, 'YXZ');\n if (!this.previousMagicWindowYaw && magicWindowAbsoluteEuler.y !== 0) {\n this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y;\n }\n if (this.previousMagicWindowYaw) {\n magicWindowDeltaEuler.x = magicWindowAbsoluteEuler.x;\n magicWindowDeltaEuler.y += magicWindowAbsoluteEuler.y - this.previousMagicWindowYaw;\n magicWindowDeltaEuler.z = magicWindowAbsoluteEuler.z;\n this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y;\n }\n }\n },\n\n /**\n * Translate mouse drag into rotation.\n *\n * Dragging up and down rotates the camera around the X-axis (yaw).\n * Dragging left and right rotates the camera around the Y-axis (pitch).\n */\n onMouseMove: function (event) {\n var direction;\n var movementX;\n var movementY;\n var pitchObject = this.pitchObject;\n var previousMouseEvent = this.previousMouseEvent;\n var yawObject = this.yawObject;\n\n // Not dragging or not enabled.\n if (!this.data.enabled || (!this.mouseDown && !this.pointerLocked)) { return; }\n\n // Calculate delta.\n if (this.pointerLocked) {\n movementX = event.movementX || event.mozMovementX || 0;\n movementY = event.movementY || event.mozMovementY || 0;\n } else {\n movementX = event.screenX - previousMouseEvent.screenX;\n movementY = event.screenY - previousMouseEvent.screenY;\n }\n this.previousMouseEvent = event;\n\n // Calculate rotation.\n direction = this.data.reverseMouseDrag ? 1 : -1;\n yawObject.rotation.y += movementX * 0.002 * direction;\n pitchObject.rotation.x += movementY * 0.002 * direction;\n pitchObject.rotation.x = Math.max(-PI_2, Math.min(PI_2, pitchObject.rotation.x));\n },\n\n /**\n * Register mouse down to detect mouse drag.\n */\n onMouseDown: function (evt) {\n var sceneEl = this.el.sceneEl;\n if (!this.data.enabled || sceneEl.is('vr-mode')) { return; }\n // Handle only primary button.\n if (evt.button !== 0) { return; }\n\n var canvasEl = sceneEl && sceneEl.canvas;\n\n this.mouseDown = true;\n this.previousMouseEvent = evt;\n this.showGrabbingCursor();\n\n if (this.data.pointerLockEnabled && !this.pointerLocked) {\n if (canvasEl.requestPointerLock) {\n canvasEl.requestPointerLock();\n } else if (canvasEl.mozRequestPointerLock) {\n canvasEl.mozRequestPointerLock();\n }\n }\n },\n\n /**\n * Shows grabbing cursor on scene\n */\n showGrabbingCursor: function () {\n this.el.sceneEl.canvas.style.cursor = 'grabbing';\n },\n\n /**\n * Hides grabbing cursor on scene\n */\n hideGrabbingCursor: function () {\n this.el.sceneEl.canvas.style.cursor = '';\n },\n\n /**\n * Register mouse up to detect release of mouse drag.\n */\n onMouseUp: function () {\n this.mouseDown = false;\n this.hideGrabbingCursor();\n },\n\n /**\n * Register touch down to detect touch drag.\n */\n onTouchStart: function (evt) {\n if (evt.touches.length !== 1 ||\n !this.data.touchEnabled ||\n this.el.sceneEl.is('vr-mode')) { return; }\n this.touchStart = {\n x: evt.touches[0].pageX,\n y: evt.touches[0].pageY\n };\n this.touchStarted = true;\n },\n\n /**\n * Translate touch move to Y-axis rotation.\n */\n onTouchMove: function (evt) {\n var direction;\n var canvas = this.el.sceneEl.canvas;\n var deltaY;\n var yawObject = this.yawObject;\n\n if (!this.touchStarted || !this.data.touchEnabled) { return; }\n\n deltaY = 2 * Math.PI * (evt.touches[0].pageX - this.touchStart.x) / canvas.clientWidth;\n\n direction = this.data.reverseTouchDrag ? 1 : -1;\n // Limit touch orientaion to to yaw (y axis).\n yawObject.rotation.y -= deltaY * 0.5 * direction;\n this.touchStart = {\n x: evt.touches[0].pageX,\n y: evt.touches[0].pageY\n };\n },\n\n /**\n * Register touch end to detect release of touch drag.\n */\n onTouchEnd: function () {\n this.touchStarted = false;\n },\n\n /**\n * Save pose.\n */\n onEnterVR: function () {\n if (!this.el.sceneEl.checkHeadsetConnected()) { return; }\n this.saveCameraPose();\n this.el.object3D.position.set(0, 0, 0);\n this.el.object3D.rotation.set(0, 0, 0);\n this.el.object3D.updateMatrix();\n },\n\n /**\n * Restore the pose.\n */\n onExitVR: function () {\n if (!this.el.sceneEl.checkHeadsetConnected()) { return; }\n this.restoreCameraPose();\n this.previousHMDPosition.set(0, 0, 0);\n },\n\n /**\n * Update Pointer Lock state.\n */\n onPointerLockChange: function () {\n this.pointerLocked = !!(document.pointerLockElement || document.mozPointerLockElement);\n },\n\n /**\n * Recover from Pointer Lock error.\n */\n onPointerLockError: function () {\n this.pointerLocked = false;\n },\n\n // Exits pointer-locked mode.\n exitPointerLock: function () {\n document.exitPointerLock();\n this.pointerLocked = false;\n },\n\n /**\n * Toggle the feature of showing/hiding the grab cursor.\n */\n updateGrabCursor: function (enabled) {\n var sceneEl = this.el.sceneEl;\n\n function enableGrabCursor () { sceneEl.canvas.classList.add('a-grab-cursor'); }\n function disableGrabCursor () { sceneEl.canvas.classList.remove('a-grab-cursor'); }\n\n if (!sceneEl.canvas) {\n if (enabled) {\n sceneEl.addEventListener('render-target-loaded', enableGrabCursor);\n } else {\n sceneEl.addEventListener('render-target-loaded', disableGrabCursor);\n }\n return;\n }\n\n if (enabled) {\n enableGrabCursor();\n return;\n }\n disableGrabCursor();\n },\n\n /**\n * Save camera pose before entering VR to restore later if exiting.\n */\n saveCameraPose: function () {\n var el = this.el;\n\n this.savedPose.position.copy(el.object3D.position);\n this.savedPose.rotation.copy(el.object3D.rotation);\n this.hasSavedPose = true;\n },\n\n /**\n * Reset camera pose to before entering VR.\n */\n restoreCameraPose: function () {\n var el = this.el;\n var savedPose = this.savedPose;\n\n if (!this.hasSavedPose) { return; }\n\n // Reset camera orientation.\n el.object3D.position.copy(savedPose.position);\n el.object3D.rotation.copy(savedPose.rotation);\n this.hasSavedPose = false;\n }\n});\n", - "/* global Promise */\nvar utils = require('../utils/');\nvar component = require('../core/component');\nvar THREE = require('../lib/three');\nvar shader = require('../core/shader');\n\nvar error = utils.debug('components:material:error');\nvar registerComponent = component.registerComponent;\nvar shaders = shader.shaders;\nvar shaderNames = shader.shaderNames;\n\n/**\n * Material component.\n *\n * @member {object} shader - Determines how material is shaded. Defaults to `standard`,\n * three.js's implementation of PBR. Another standard shading model is `flat` which\n * uses MeshBasicMaterial.\n */\nmodule.exports.Component = registerComponent('material', {\n schema: {\n alphaTest: {default: 0.0, min: 0.0, max: 1.0},\n depthTest: {default: true},\n depthWrite: {default: true},\n flatShading: {default: false},\n npot: {default: false},\n offset: {type: 'vec2', default: {x: 0, y: 0}},\n opacity: {default: 1.0, min: 0.0, max: 1.0},\n repeat: {type: 'vec2', default: {x: 1, y: 1}},\n shader: {default: 'standard', oneOf: shaderNames, schemaChange: true},\n side: {default: 'front', oneOf: ['front', 'back', 'double']},\n transparent: {default: false},\n vertexColors: {type: 'string', default: 'none', oneOf: ['face', 'vertex']},\n visible: {default: true},\n blending: {default: 'normal', oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply']}\n },\n\n init: function () {\n this.material = null;\n },\n\n /**\n * Update or create material.\n *\n * @param {object|null} oldData\n */\n update: function (oldData) {\n var data = this.data;\n if (!this.shader || data.shader !== oldData.shader) {\n this.updateShader(data.shader);\n }\n this.shader.update(this.data);\n this.updateMaterial(oldData);\n },\n\n updateSchema: function (data) {\n var currentShader;\n var newShader;\n var schema;\n var shader;\n\n newShader = data && data.shader;\n currentShader = this.oldData && this.oldData.shader;\n shader = newShader || currentShader;\n schema = shaders[shader] && shaders[shader].schema;\n\n if (!schema) { error('Unknown shader schema ' + shader); }\n if (currentShader && newShader === currentShader) { return; }\n this.extendSchema(schema);\n this.updateBehavior();\n },\n\n updateBehavior: function () {\n var key;\n var sceneEl = this.el.sceneEl;\n var schema = this.schema;\n var self = this;\n var tickProperties;\n\n function tickTime (time, delta) {\n var key;\n for (key in tickProperties) {\n tickProperties[key] = time;\n }\n self.shader.update(tickProperties);\n }\n\n this.tick = undefined;\n\n tickProperties = {};\n for (key in schema) {\n if (schema[key].type === 'time') {\n this.tick = tickTime;\n tickProperties[key] = true;\n }\n }\n\n if (!sceneEl) { return; }\n if (this.tick) {\n sceneEl.addBehavior(this);\n } else {\n sceneEl.removeBehavior(this);\n }\n },\n\n updateShader: function (shaderName) {\n var data = this.data;\n var Shader = shaders[shaderName] && shaders[shaderName].Shader;\n var shaderInstance;\n\n if (!Shader) { throw new Error('Unknown shader ' + shaderName); }\n\n // Get material from A-Frame shader.\n shaderInstance = this.shader = new Shader();\n shaderInstance.el = this.el;\n shaderInstance.init(data);\n this.setMaterial(shaderInstance.material);\n this.updateSchema(data);\n },\n\n /**\n * Set and update base material properties.\n * Set `needsUpdate` when needed.\n */\n updateMaterial: function (oldData) {\n var data = this.data;\n var material = this.material;\n var oldDataHasKeys;\n\n // Base material properties.\n material.alphaTest = data.alphaTest;\n material.depthTest = data.depthTest !== false;\n material.depthWrite = data.depthWrite !== false;\n material.opacity = data.opacity;\n material.flatShading = data.flatShading;\n material.side = parseSide(data.side);\n material.transparent = data.transparent !== false || data.opacity < 1.0;\n material.vertexColors = parseVertexColors(data.vertexColors);\n material.visible = data.visible;\n material.blending = parseBlending(data.blending);\n\n // Check if material needs update.\n for (oldDataHasKeys in oldData) { break; }\n if (oldDataHasKeys &&\n (oldData.alphaTest !== data.alphaTest ||\n oldData.side !== data.side ||\n oldData.vertexColors !== data.vertexColors)) {\n material.needsUpdate = true;\n }\n },\n\n /**\n * Remove material on remove (callback).\n * Dispose of it from memory and unsubscribe from scene updates.\n */\n remove: function () {\n var defaultMaterial = new THREE.MeshBasicMaterial();\n var material = this.material;\n var object3D = this.el.getObject3D('mesh');\n if (object3D) { object3D.material = defaultMaterial; }\n disposeMaterial(material, this.system);\n },\n\n /**\n * (Re)create new material. Has side-effects of setting `this.material` and updating\n * material registration in scene.\n *\n * @param {object} data - Material component data.\n * @param {object} type - Material type to create.\n * @returns {object} Material.\n */\n setMaterial: function (material) {\n var el = this.el;\n var mesh;\n var system = this.system;\n\n if (this.material) { disposeMaterial(this.material, system); }\n\n this.material = material;\n system.registerMaterial(material);\n\n // Set on mesh. If mesh does not exist, wait for it.\n mesh = el.getObject3D('mesh');\n if (mesh) {\n mesh.material = material;\n } else {\n el.addEventListener('object3dset', function waitForMesh (evt) {\n if (evt.detail.type !== 'mesh' || evt.target !== el) { return; }\n el.getObject3D('mesh').material = material;\n el.removeEventListener('object3dset', waitForMesh);\n });\n }\n }\n});\n\n/**\n * Return a three.js constant determining which material face sides to render\n * based on the side parameter (passed as a component property).\n *\n * @param {string} [side=front] - `front`, `back`, or `double`.\n * @returns {number} THREE.FrontSide, THREE.BackSide, or THREE.DoubleSide.\n */\nfunction parseSide (side) {\n switch (side) {\n case 'back': {\n return THREE.BackSide;\n }\n case 'double': {\n return THREE.DoubleSide;\n }\n default: {\n // Including case `front`.\n return THREE.FrontSide;\n }\n }\n}\n\n/**\n * Return a three.js constant determining vertex coloring.\n */\nfunction parseVertexColors (coloring) {\n switch (coloring) {\n case 'face': {\n return THREE.FaceColors;\n }\n case 'vertex': {\n return THREE.VertexColors;\n }\n default: {\n return THREE.NoColors;\n }\n }\n}\n\n/**\n * Return a three.js constant determining blending\n *\n * @param {string} [blending=normal]\n * - `none`, additive`, `subtractive`,`multiply` or `normal`.\n * @returns {number}\n */\nfunction parseBlending (blending) {\n switch (blending) {\n case 'none': {\n return THREE.NoBlending;\n }\n case 'additive': {\n return THREE.AdditiveBlending;\n }\n case 'subtractive': {\n return THREE.SubtractiveBlending;\n }\n case 'multiply': {\n return THREE.MultiplyBlending;\n }\n default: {\n return THREE.NormalBlending;\n }\n }\n}\n\n/**\n * Dispose of material from memory and unsubscribe material from scene updates like fog.\n */\nfunction disposeMaterial (material, system) {\n material.dispose();\n system.unregisterMaterial(material);\n}\n", + "/* global DeviceOrientationEvent */\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\nvar bind = utils.bind;\n\n// To avoid recalculation at every mouse movement tick\nvar PI_2 = Math.PI / 2;\n\n/**\n * look-controls. Update entity pose, factoring mouse, touch, and WebVR API data.\n */\nmodule.exports.Component = registerComponent('look-controls', {\n dependencies: ['position', 'rotation'],\n\n schema: {\n enabled: {default: true},\n hmdEnabled: {default: true},\n pointerLockEnabled: {default: false},\n reverseMouseDrag: {default: false},\n reverseTouchDrag: {default: false},\n touchEnabled: {default: true}\n },\n\n init: function () {\n this.deltaYaw = 0;\n this.previousHMDPosition = new THREE.Vector3();\n this.hmdQuaternion = new THREE.Quaternion();\n this.magicWindowAbsoluteEuler = new THREE.Euler();\n this.magicWindowDeltaEuler = new THREE.Euler();\n this.position = new THREE.Vector3();\n // To save / restore camera pose\n this.savedRotation = new THREE.Vector3();\n this.savedPosition = new THREE.Vector3();\n this.magicWindowObject = new THREE.Object3D();\n this.rotation = {};\n this.deltaRotation = {};\n this.savedPose = null;\n this.pointerLocked = false;\n this.setupMouseControls();\n this.bindMethods();\n\n this.setupMagicWindowControls();\n\n this.savedPose = {\n position: new THREE.Vector3(),\n rotation: new THREE.Euler()\n };\n\n // Call enter VR handler if the scene has entered VR before the event listeners attached.\n if (this.el.sceneEl.is('vr-mode')) { this.onEnterVR(); }\n },\n\n setupMagicWindowControls: function () {\n var magicWindowControls;\n\n // Only on mobile devices and only enabled if DeviceOrientation permission has been granted.\n if (utils.device.isMobile()) {\n magicWindowControls = this.magicWindowControls = new THREE.DeviceOrientationControls(this.magicWindowObject);\n if (typeof DeviceOrientationEvent !== 'undefined' && DeviceOrientationEvent.requestPermission) {\n magicWindowControls.enabled = false;\n if (this.el.sceneEl.components['device-orientation-permission-ui'].permissionGranted) {\n magicWindowControls.enabled = true;\n } else {\n this.el.sceneEl.addEventListener('deviceorientationpermissiongranted', function () {\n magicWindowControls.enabled = true;\n });\n }\n }\n }\n },\n\n update: function (oldData) {\n var data = this.data;\n\n // Disable grab cursor classes if no longer enabled.\n if (data.enabled !== oldData.enabled) {\n this.updateGrabCursor(data.enabled);\n }\n\n // Reset pitch and yaw if disabling HMD.\n if (oldData && !data.hmdEnabled && !oldData.hmdEnabled) {\n this.pitchObject.rotation.set(0, 0, 0);\n this.yawObject.rotation.set(0, 0, 0);\n }\n\n if (oldData && !data.pointerLockEnabled !== oldData.pointerLockEnabled) {\n this.removeEventListeners();\n this.addEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n }\n },\n\n tick: function (t) {\n var data = this.data;\n if (!data.enabled) { return; }\n this.updateOrientation();\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n },\n\n remove: function () {\n this.removeEventListeners();\n if (this.pointerLocked) { this.exitPointerLock(); }\n },\n\n bindMethods: function () {\n this.onMouseDown = bind(this.onMouseDown, this);\n this.onMouseMove = bind(this.onMouseMove, this);\n this.onMouseUp = bind(this.onMouseUp, this);\n this.onTouchStart = bind(this.onTouchStart, this);\n this.onTouchMove = bind(this.onTouchMove, this);\n this.onTouchEnd = bind(this.onTouchEnd, this);\n this.onEnterVR = bind(this.onEnterVR, this);\n this.onExitVR = bind(this.onExitVR, this);\n this.onPointerLockChange = bind(this.onPointerLockChange, this);\n this.onPointerLockError = bind(this.onPointerLockError, this);\n },\n\n /**\n * Set up states and Object3Ds needed to store rotation data.\n */\n setupMouseControls: function () {\n this.mouseDown = false;\n this.pitchObject = new THREE.Object3D();\n this.yawObject = new THREE.Object3D();\n this.yawObject.position.y = 10;\n this.yawObject.add(this.pitchObject);\n },\n\n /**\n * Add mouse and touch event listeners to canvas.\n */\n addEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n var canvasEl = sceneEl.canvas;\n\n // Wait for canvas to load.\n if (!canvasEl) {\n sceneEl.addEventListener('render-target-loaded', bind(this.addEventListeners, this));\n return;\n }\n\n // Mouse events.\n canvasEl.addEventListener('mousedown', this.onMouseDown, false);\n window.addEventListener('mousemove', this.onMouseMove, false);\n window.addEventListener('mouseup', this.onMouseUp, false);\n\n // Touch events.\n canvasEl.addEventListener('touchstart', this.onTouchStart);\n window.addEventListener('touchmove', this.onTouchMove);\n window.addEventListener('touchend', this.onTouchEnd);\n\n // sceneEl events.\n sceneEl.addEventListener('enter-vr', this.onEnterVR);\n sceneEl.addEventListener('exit-vr', this.onExitVR);\n\n // Pointer Lock events.\n if (this.data.pointerLockEnabled) {\n document.addEventListener('pointerlockchange', this.onPointerLockChange, false);\n document.addEventListener('mozpointerlockchange', this.onPointerLockChange, false);\n document.addEventListener('pointerlockerror', this.onPointerLockError, false);\n }\n },\n\n /**\n * Remove mouse and touch event listeners from canvas.\n */\n removeEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n var canvasEl = sceneEl && sceneEl.canvas;\n\n if (!canvasEl) { return; }\n\n // Mouse events.\n canvasEl.removeEventListener('mousedown', this.onMouseDown);\n window.removeEventListener('mousemove', this.onMouseMove);\n window.removeEventListener('mouseup', this.onMouseUp);\n\n // Touch events.\n canvasEl.removeEventListener('touchstart', this.onTouchStart);\n window.removeEventListener('touchmove', this.onTouchMove);\n window.removeEventListener('touchend', this.onTouchEnd);\n\n // sceneEl events.\n sceneEl.removeEventListener('enter-vr', this.onEnterVR);\n sceneEl.removeEventListener('exit-vr', this.onExitVR);\n\n // Pointer Lock events.\n document.removeEventListener('pointerlockchange', this.onPointerLockChange, false);\n document.removeEventListener('mozpointerlockchange', this.onPointerLockChange, false);\n document.removeEventListener('pointerlockerror', this.onPointerLockError, false);\n },\n\n /**\n * Update orientation for mobile, mouse drag, and headset.\n * Mouse-drag only enabled if HMD is not active.\n */\n updateOrientation: (function () {\n var poseMatrix = new THREE.Matrix4();\n\n return function () {\n var object3D = this.el.object3D;\n var pitchObject = this.pitchObject;\n var yawObject = this.yawObject;\n var pose;\n var sceneEl = this.el.sceneEl;\n\n // In VR mode, THREE is in charge of updating the camera pose.\n if (sceneEl.is('vr-mode') && sceneEl.checkHeadsetConnected()) {\n // With WebXR THREE applies headset pose to the object3D matrixWorld internally.\n // Reflect values back on position, rotation, scale for getAttribute to return the expected values.\n if (sceneEl.hasWebXR) {\n pose = sceneEl.renderer.xr.getCameraPose();\n if (pose) {\n poseMatrix.elements = pose.transform.matrix;\n poseMatrix.decompose(object3D.position, object3D.rotation, object3D.scale);\n }\n }\n return;\n }\n\n this.updateMagicWindowOrientation();\n\n // On mobile, do camera rotation with touch events and sensors.\n object3D.rotation.x = this.magicWindowDeltaEuler.x + pitchObject.rotation.x;\n object3D.rotation.y = this.magicWindowDeltaEuler.y + yawObject.rotation.y;\n object3D.rotation.z = this.magicWindowDeltaEuler.z;\n };\n })(),\n\n updateMagicWindowOrientation: function () {\n var magicWindowAbsoluteEuler = this.magicWindowAbsoluteEuler;\n var magicWindowDeltaEuler = this.magicWindowDeltaEuler;\n // Calculate magic window HMD quaternion.\n if (this.magicWindowControls && this.magicWindowControls.enabled) {\n this.magicWindowControls.update();\n magicWindowAbsoluteEuler.setFromQuaternion(this.magicWindowObject.quaternion, 'YXZ');\n if (!this.previousMagicWindowYaw && magicWindowAbsoluteEuler.y !== 0) {\n this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y;\n }\n if (this.previousMagicWindowYaw) {\n magicWindowDeltaEuler.x = magicWindowAbsoluteEuler.x;\n magicWindowDeltaEuler.y += magicWindowAbsoluteEuler.y - this.previousMagicWindowYaw;\n magicWindowDeltaEuler.z = magicWindowAbsoluteEuler.z;\n this.previousMagicWindowYaw = magicWindowAbsoluteEuler.y;\n }\n }\n },\n\n /**\n * Translate mouse drag into rotation.\n *\n * Dragging up and down rotates the camera around the X-axis (yaw).\n * Dragging left and right rotates the camera around the Y-axis (pitch).\n */\n onMouseMove: function (event) {\n var direction;\n var movementX;\n var movementY;\n var pitchObject = this.pitchObject;\n var previousMouseEvent = this.previousMouseEvent;\n var yawObject = this.yawObject;\n\n // Not dragging or not enabled.\n if (!this.data.enabled || (!this.mouseDown && !this.pointerLocked)) { return; }\n\n // Calculate delta.\n if (this.pointerLocked) {\n movementX = event.movementX || event.mozMovementX || 0;\n movementY = event.movementY || event.mozMovementY || 0;\n } else {\n movementX = event.screenX - previousMouseEvent.screenX;\n movementY = event.screenY - previousMouseEvent.screenY;\n }\n this.previousMouseEvent = event;\n\n // Calculate rotation.\n direction = this.data.reverseMouseDrag ? 1 : -1;\n yawObject.rotation.y += movementX * 0.002 * direction;\n pitchObject.rotation.x += movementY * 0.002 * direction;\n pitchObject.rotation.x = Math.max(-PI_2, Math.min(PI_2, pitchObject.rotation.x));\n },\n\n /**\n * Register mouse down to detect mouse drag.\n */\n onMouseDown: function (evt) {\n var sceneEl = this.el.sceneEl;\n if (!this.data.enabled || (sceneEl.is('vr-mode') && sceneEl.checkHeadsetConnected())) { return; }\n // Handle only primary button.\n if (evt.button !== 0) { return; }\n\n var canvasEl = sceneEl && sceneEl.canvas;\n\n this.mouseDown = true;\n this.previousMouseEvent = evt;\n this.showGrabbingCursor();\n\n if (this.data.pointerLockEnabled && !this.pointerLocked) {\n if (canvasEl.requestPointerLock) {\n canvasEl.requestPointerLock();\n } else if (canvasEl.mozRequestPointerLock) {\n canvasEl.mozRequestPointerLock();\n }\n }\n },\n\n /**\n * Shows grabbing cursor on scene\n */\n showGrabbingCursor: function () {\n this.el.sceneEl.canvas.style.cursor = 'grabbing';\n },\n\n /**\n * Hides grabbing cursor on scene\n */\n hideGrabbingCursor: function () {\n this.el.sceneEl.canvas.style.cursor = '';\n },\n\n /**\n * Register mouse up to detect release of mouse drag.\n */\n onMouseUp: function () {\n this.mouseDown = false;\n this.hideGrabbingCursor();\n },\n\n /**\n * Register touch down to detect touch drag.\n */\n onTouchStart: function (evt) {\n if (evt.touches.length !== 1 ||\n !this.data.touchEnabled ||\n this.el.sceneEl.is('vr-mode')) { return; }\n this.touchStart = {\n x: evt.touches[0].pageX,\n y: evt.touches[0].pageY\n };\n this.touchStarted = true;\n },\n\n /**\n * Translate touch move to Y-axis rotation.\n */\n onTouchMove: function (evt) {\n var direction;\n var canvas = this.el.sceneEl.canvas;\n var deltaY;\n var yawObject = this.yawObject;\n\n if (!this.touchStarted || !this.data.touchEnabled) { return; }\n\n deltaY = 2 * Math.PI * (evt.touches[0].pageX - this.touchStart.x) / canvas.clientWidth;\n\n direction = this.data.reverseTouchDrag ? 1 : -1;\n // Limit touch orientaion to to yaw (y axis).\n yawObject.rotation.y -= deltaY * 0.5 * direction;\n this.touchStart = {\n x: evt.touches[0].pageX,\n y: evt.touches[0].pageY\n };\n },\n\n /**\n * Register touch end to detect release of touch drag.\n */\n onTouchEnd: function () {\n this.touchStarted = false;\n },\n\n /**\n * Save pose.\n */\n onEnterVR: function () {\n var sceneEl = this.el.sceneEl;\n if (!sceneEl.checkHeadsetConnected()) { return; }\n this.saveCameraPose();\n this.el.object3D.position.set(0, 0, 0);\n this.el.object3D.rotation.set(0, 0, 0);\n if (sceneEl.hasWebXR) {\n this.el.object3D.matrixAutoUpdate = false;\n this.el.object3D.updateMatrix();\n }\n },\n\n /**\n * Restore the pose.\n */\n onExitVR: function () {\n if (!this.el.sceneEl.checkHeadsetConnected()) { return; }\n this.restoreCameraPose();\n this.previousHMDPosition.set(0, 0, 0);\n this.el.object3D.matrixAutoUpdate = true;\n },\n\n /**\n * Update Pointer Lock state.\n */\n onPointerLockChange: function () {\n this.pointerLocked = !!(document.pointerLockElement || document.mozPointerLockElement);\n },\n\n /**\n * Recover from Pointer Lock error.\n */\n onPointerLockError: function () {\n this.pointerLocked = false;\n },\n\n // Exits pointer-locked mode.\n exitPointerLock: function () {\n document.exitPointerLock();\n this.pointerLocked = false;\n },\n\n /**\n * Toggle the feature of showing/hiding the grab cursor.\n */\n updateGrabCursor: function (enabled) {\n var sceneEl = this.el.sceneEl;\n\n function enableGrabCursor () { sceneEl.canvas.classList.add('a-grab-cursor'); }\n function disableGrabCursor () { sceneEl.canvas.classList.remove('a-grab-cursor'); }\n\n if (!sceneEl.canvas) {\n if (enabled) {\n sceneEl.addEventListener('render-target-loaded', enableGrabCursor);\n } else {\n sceneEl.addEventListener('render-target-loaded', disableGrabCursor);\n }\n return;\n }\n\n if (enabled) {\n enableGrabCursor();\n return;\n }\n disableGrabCursor();\n },\n\n /**\n * Save camera pose before entering VR to restore later if exiting.\n */\n saveCameraPose: function () {\n var el = this.el;\n\n this.savedPose.position.copy(el.object3D.position);\n this.savedPose.rotation.copy(el.object3D.rotation);\n this.hasSavedPose = true;\n },\n\n /**\n * Reset camera pose to before entering VR.\n */\n restoreCameraPose: function () {\n var el = this.el;\n var savedPose = this.savedPose;\n\n if (!this.hasSavedPose) { return; }\n\n // Reset camera orientation.\n el.object3D.position.copy(savedPose.position);\n el.object3D.rotation.copy(savedPose.rotation);\n this.hasSavedPose = false;\n }\n});\n", + "var bind = require('../utils/bind');\nvar registerComponent = require('../core/component').registerComponent;\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\n// See Profiles Registry:\n// https://github.com/immersive-web/webxr-input-profiles/tree/master/packages/registry\n// TODO: Add a more robust system for deriving gamepad name.\nvar GAMEPAD_ID_PREFIX = 'magicleap';\nvar GAMEPAD_ID_SUFFIX = '-one';\nvar GAMEPAD_ID_COMPOSITE = GAMEPAD_ID_PREFIX + GAMEPAD_ID_SUFFIX;\n\nvar MAGICLEAP_CONTROLLER_MODEL_GLB_URL = 'https://cdn.aframe.io/controllers/magicleap/magicleap-one-controller.glb';\n\n/**\n * Button IDs:\n * 0 - trigger\n * 1 - grip\n * 2 - touchpad\n * 3 - menu (never dispatched on this layer)\n *\n * Axis:\n * 0 - touchpad x axis\n * 1 - touchpad y axis\n */\nvar INPUT_MAPPING_WEBXR = {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'grip', 'touchpad', 'menu']\n};\n\n/**\n * Magic Leap Controls\n * Interface with Magic Leap control and map Gamepad events to controller\n * buttons: trigger, grip, touchpad, and menu.\n * Load a controller model.\n */\nmodule.exports.Component = registerComponent('magicleap-controls', {\n schema: {\n hand: {default: 'none'},\n model: {default: true},\n orientationOffset: {type: 'vec3'}\n },\n\n mapping: INPUT_MAPPING_WEBXR,\n\n init: function () {\n var self = this;\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.previousButtonValues = {};\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n\n this.bindMethods();\n },\n\n update: function () {\n var data = this.data;\n this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2;\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('axismove', this.onAxisMoved);\n el.addEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n var data = this.data;\n checkControllerPresentAndSetup(this, GAMEPAD_ID_COMPOSITE,\n {index: this.controllerIndex, hand: data.hand});\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n\n el.setAttribute('tracked-controls', {\n // TODO: verify expected behavior between reserved prefixes.\n idPrefix: GAMEPAD_ID_COMPOSITE,\n hand: data.hand,\n controller: this.controllerIndex,\n orientationOffset: data.orientationOffset\n });\n\n // Load model.\n if (!this.data.model) { return; }\n this.el.setAttribute('gltf-model', MAGICLEAP_CONTROLLER_MODEL_GLB_URL);\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n // Note that due to gamepadconnected event propagation issues, we don't rely on events.\n this.checkIfControllerPresent();\n },\n\n /**\n * Rotate the trigger button based on how hard the trigger is pressed.\n */\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n var analogValue;\n\n if (!button) { return; }\n if (button === 'trigger') {\n analogValue = evt.detail.state.value;\n console.log('analog value of trigger press: ' + analogValue);\n }\n\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n // our glb scale is too large.\n controllerObject3D.scale.set(0.01, 0.01, 0.01);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {},\n\n setButtonColor: function (buttonName, color) {}\n\n});\n", + "/* global Promise */\nvar utils = require('../utils/');\nvar component = require('../core/component');\nvar THREE = require('../lib/three');\nvar shader = require('../core/shader');\n\nvar error = utils.debug('components:material:error');\nvar registerComponent = component.registerComponent;\nvar shaders = shader.shaders;\nvar shaderNames = shader.shaderNames;\n\n/**\n * Material component.\n *\n * @member {object} shader - Determines how material is shaded. Defaults to `standard`,\n * three.js's implementation of PBR. Another standard shading model is `flat` which\n * uses MeshBasicMaterial.\n */\nmodule.exports.Component = registerComponent('material', {\n schema: {\n alphaTest: {default: 0.0, min: 0.0, max: 1.0},\n depthTest: {default: true},\n depthWrite: {default: true},\n flatShading: {default: false},\n npot: {default: false},\n offset: {type: 'vec2', default: {x: 0, y: 0}},\n opacity: {default: 1.0, min: 0.0, max: 1.0},\n repeat: {type: 'vec2', default: {x: 1, y: 1}},\n shader: {default: 'standard', oneOf: shaderNames, schemaChange: true},\n side: {default: 'front', oneOf: ['front', 'back', 'double']},\n transparent: {default: false},\n vertexColors: {type: 'string', default: 'none', oneOf: ['face', 'vertex']},\n visible: {default: true},\n blending: {default: 'normal', oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply']},\n dithering: {default: true}\n },\n\n init: function () {\n this.material = null;\n },\n\n /**\n * Update or create material.\n *\n * @param {object|null} oldData\n */\n update: function (oldData) {\n var data = this.data;\n if (!this.shader || data.shader !== oldData.shader) {\n this.updateShader(data.shader);\n }\n this.shader.update(this.data);\n this.updateMaterial(oldData);\n },\n\n updateSchema: function (data) {\n var currentShader;\n var newShader;\n var schema;\n var shader;\n\n newShader = data && data.shader;\n currentShader = this.oldData && this.oldData.shader;\n shader = newShader || currentShader;\n schema = shaders[shader] && shaders[shader].schema;\n\n if (!schema) { error('Unknown shader schema ' + shader); }\n if (currentShader && newShader === currentShader) { return; }\n this.extendSchema(schema);\n this.updateBehavior();\n },\n\n updateBehavior: function () {\n var key;\n var sceneEl = this.el.sceneEl;\n var schema = this.schema;\n var self = this;\n var tickProperties;\n\n function tickTime (time, delta) {\n var key;\n for (key in tickProperties) {\n tickProperties[key] = time;\n }\n self.shader.update(tickProperties);\n }\n\n this.tick = undefined;\n\n tickProperties = {};\n for (key in schema) {\n if (schema[key].type === 'time') {\n this.tick = tickTime;\n tickProperties[key] = true;\n }\n }\n\n if (!sceneEl) { return; }\n if (this.tick) {\n sceneEl.addBehavior(this);\n } else {\n sceneEl.removeBehavior(this);\n }\n },\n\n updateShader: function (shaderName) {\n var data = this.data;\n var Shader = shaders[shaderName] && shaders[shaderName].Shader;\n var shaderInstance;\n\n if (!Shader) { throw new Error('Unknown shader ' + shaderName); }\n\n // Get material from A-Frame shader.\n shaderInstance = this.shader = new Shader();\n shaderInstance.el = this.el;\n shaderInstance.init(data);\n this.setMaterial(shaderInstance.material);\n this.updateSchema(data);\n },\n\n /**\n * Set and update base material properties.\n * Set `needsUpdate` when needed.\n */\n updateMaterial: function (oldData) {\n var data = this.data;\n var material = this.material;\n var oldDataHasKeys;\n\n // Base material properties.\n material.alphaTest = data.alphaTest;\n material.depthTest = data.depthTest !== false;\n material.depthWrite = data.depthWrite !== false;\n material.opacity = data.opacity;\n material.flatShading = data.flatShading;\n material.side = parseSide(data.side);\n material.transparent = data.transparent !== false || data.opacity < 1.0;\n material.vertexColors = parseVertexColors(data.vertexColors);\n material.visible = data.visible;\n material.blending = parseBlending(data.blending);\n material.dithering = data.dithering;\n\n // Check if material needs update.\n for (oldDataHasKeys in oldData) { break; }\n if (oldDataHasKeys &&\n (oldData.alphaTest !== data.alphaTest ||\n oldData.side !== data.side ||\n oldData.vertexColors !== data.vertexColors)) {\n material.needsUpdate = true;\n }\n },\n\n /**\n * Remove material on remove (callback).\n * Dispose of it from memory and unsubscribe from scene updates.\n */\n remove: function () {\n var defaultMaterial = new THREE.MeshBasicMaterial();\n var material = this.material;\n var object3D = this.el.getObject3D('mesh');\n if (object3D) { object3D.material = defaultMaterial; }\n disposeMaterial(material, this.system);\n },\n\n /**\n * (Re)create new material. Has side-effects of setting `this.material` and updating\n * material registration in scene.\n *\n * @param {object} data - Material component data.\n * @param {object} type - Material type to create.\n * @returns {object} Material.\n */\n setMaterial: function (material) {\n var el = this.el;\n var mesh;\n var system = this.system;\n\n if (this.material) { disposeMaterial(this.material, system); }\n\n this.material = material;\n system.registerMaterial(material);\n\n // Set on mesh. If mesh does not exist, wait for it.\n mesh = el.getObject3D('mesh');\n if (mesh) {\n mesh.material = material;\n } else {\n el.addEventListener('object3dset', function waitForMesh (evt) {\n if (evt.detail.type !== 'mesh' || evt.target !== el) { return; }\n el.getObject3D('mesh').material = material;\n el.removeEventListener('object3dset', waitForMesh);\n });\n }\n }\n});\n\n/**\n * Return a three.js constant determining which material face sides to render\n * based on the side parameter (passed as a component property).\n *\n * @param {string} [side=front] - `front`, `back`, or `double`.\n * @returns {number} THREE.FrontSide, THREE.BackSide, or THREE.DoubleSide.\n */\nfunction parseSide (side) {\n switch (side) {\n case 'back': {\n return THREE.BackSide;\n }\n case 'double': {\n return THREE.DoubleSide;\n }\n default: {\n // Including case `front`.\n return THREE.FrontSide;\n }\n }\n}\n\n/**\n * Return a three.js constant determining vertex coloring.\n */\nfunction parseVertexColors (coloring) {\n switch (coloring) {\n case 'face': {\n return THREE.FaceColors;\n }\n case 'vertex': {\n return THREE.VertexColors;\n }\n default: {\n return THREE.NoColors;\n }\n }\n}\n\n/**\n * Return a three.js constant determining blending\n *\n * @param {string} [blending=normal]\n * - `none`, additive`, `subtractive`,`multiply` or `normal`.\n * @returns {number}\n */\nfunction parseBlending (blending) {\n switch (blending) {\n case 'none': {\n return THREE.NoBlending;\n }\n case 'additive': {\n return THREE.AdditiveBlending;\n }\n case 'subtractive': {\n return THREE.SubtractiveBlending;\n }\n case 'multiply': {\n return THREE.MultiplyBlending;\n }\n default: {\n return THREE.NormalBlending;\n }\n }\n}\n\n/**\n * Dispose of material from memory and unsubscribe material from scene updates like fog.\n */\nfunction disposeMaterial (material, system) {\n material.dispose();\n system.unregisterMaterial(material);\n}\n", "var debug = require('../utils/debug');\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\n\nvar warn = debug('components:obj-model:warn');\n\nmodule.exports.Component = registerComponent('obj-model', {\n schema: {\n mtl: {type: 'model'},\n obj: {type: 'model'}\n },\n\n init: function () {\n var self = this;\n\n this.model = null;\n this.objLoader = new THREE.OBJLoader();\n this.mtlLoader = new THREE.MTLLoader(this.objLoader.manager);\n // Allow cross-origin images to be loaded.\n this.mtlLoader.crossOrigin = '';\n\n this.el.addEventListener('componentinitialized', function (evt) {\n if (!self.model) { return; }\n if (evt.detail.name !== 'material') { return; }\n self.applyMaterial();\n });\n },\n\n update: function () {\n var data = this.data;\n if (!data.obj) { return; }\n this.resetMesh();\n this.loadObj(data.obj, data.mtl);\n },\n\n remove: function () {\n if (!this.model) { return; }\n this.resetMesh();\n },\n\n resetMesh: function () {\n this.el.removeObject3D('mesh');\n },\n\n loadObj: function (objUrl, mtlUrl) {\n var self = this;\n var el = this.el;\n var mtlLoader = this.mtlLoader;\n var objLoader = this.objLoader;\n var rendererSystem = this.el.sceneEl.systems.renderer;\n var BASE_PATH = mtlUrl.substr(0, mtlUrl.lastIndexOf('/') + 1);\n\n if (mtlUrl) {\n // .OBJ with an .MTL.\n if (el.hasAttribute('material')) {\n warn('Material component properties are ignored when a .MTL is provided');\n }\n mtlLoader.setResourcePath(BASE_PATH);\n mtlLoader.load(mtlUrl, function (materials) {\n materials.preload();\n objLoader.setMaterials(materials);\n objLoader.load(objUrl, function (objModel) {\n self.model = objModel;\n self.model.traverse(function (object) {\n if (object.isMesh) {\n var material = object.material;\n if (material.color) rendererSystem.applyColorCorrection(material.color);\n if (material.map) rendererSystem.applyColorCorrection(material.map);\n if (material.emissive) rendererSystem.applyColorCorrection(material.emissive);\n if (material.emissiveMap) rendererSystem.applyColorCorrection(material.emissiveMap);\n }\n });\n el.setObject3D('mesh', objModel);\n el.emit('model-loaded', {format: 'obj', model: objModel});\n });\n });\n return;\n }\n\n // .OBJ only.\n objLoader.load(objUrl, function loadObjOnly (objModel) {\n self.model = objModel;\n self.applyMaterial();\n el.setObject3D('mesh', objModel);\n el.emit('model-loaded', {format: 'obj', model: objModel});\n });\n },\n\n /**\n * Apply material from material component recursively.\n */\n applyMaterial: function () {\n var material = this.el.components.material;\n if (!material) { return; }\n this.model.traverse(function (child) {\n if (child instanceof THREE.Mesh) {\n child.material = material.material;\n }\n });\n }\n});\n", - "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'oculus-go';\nvar GAMEPAD_ID_WEBVR = 'Oculus Go';\n\nvar OCULUS_GO_CONTROLLER_MODEL_URL = 'https://cdn.aframe.io/controllers/oculus/go/oculus-go-controller.gltf';\n\n// Prefix for Gen1 and Gen2 Oculus Touch Controllers.\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n/**\n * Button indices:\n * 0 - trackpad\n * 1 - trigger\n *\n * Axis:\n * 0 - trackpad x\n * 1 - trackpad y\n */\nvar INPUT_MAPPING_WEBVR = {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'trigger']\n};\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - none\n * 2 - touchpad\n *\n * Axis:\n * 0 - touchpad x\n * 1 - touchpad y\n * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-go.json\n */\nvar INPUT_MAPPING_WEBXR = {\n left: {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'none', 'touchpad']\n },\n right: {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'none', 'touchpad']\n }\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Oculus Go controls.\n * Interface with Oculus Go controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('oculus-go-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n buttonColor: {type: 'color', default: '#FFFFFF'},\n buttonTouchedColor: {type: 'color', default: '#BBBBBB'},\n buttonHighlightColor: {type: 'color', default: '#7A7A7A'},\n model: {default: true},\n orientationOffset: {type: 'vec3'},\n armModel: {default: true}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX,\n this.data.hand ? {hand: this.data.hand} : {});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n el.setAttribute('tracked-controls', {\n armModel: data.armModel,\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset\n });\n if (!this.data.model) { return; }\n this.el.setAttribute('gltf-model', OCULUS_GO_CONTROLLER_MODEL_URL);\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n // No need for onButtonChanged, since Oculus Go controller has no analog buttons.\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n\n if (!this.data.model) { return; }\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.trigger = controllerObject3D.getObjectByName('oculus_go_button_trigger');\n buttonMeshes.trackpad = controllerObject3D.getObjectByName('oculus_go_touchpad');\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var buttonMeshes = this.buttonMeshes;\n if (!buttonMeshes || !buttonMeshes[buttonName]) { return; }\n var color;\n var button;\n switch (state) {\n case 'down':\n color = this.data.buttonHighlightColor;\n break;\n case 'touchstart':\n color = this.data.buttonTouchedColor;\n break;\n default:\n color = this.data.buttonColor;\n }\n button = buttonMeshes[buttonName];\n button.material.color.set(color);\n this.rendererSystem.applyColorCorrection(button.material.color);\n }\n});\n", + "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'oculus-go';\nvar GAMEPAD_ID_WEBVR = 'Oculus Go';\n\nvar OCULUS_GO_CONTROLLER_MODEL_URL = 'https://cdn.aframe.io/controllers/oculus/go/oculus-go-controller.gltf';\n\n// Prefix for Gen1 and Gen2 Oculus Touch Controllers.\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n/**\n * Button indices:\n * 0 - trackpad\n * 1 - trigger\n *\n * Axis:\n * 0 - trackpad x\n * 1 - trackpad y\n */\nvar INPUT_MAPPING_WEBVR = {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'trigger']\n};\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - none\n * 2 - touchpad\n *\n * Axis:\n * 0 - touchpad x\n * 1 - touchpad y\n * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-go.json\n */\nvar INPUT_MAPPING_WEBXR = {\n axes: {touchpad: [0, 1]},\n buttons: ['trigger', 'none', 'touchpad']\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Oculus Go controls.\n * Interface with Oculus Go controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('oculus-go-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n buttonColor: {type: 'color', default: '#FFFFFF'},\n buttonTouchedColor: {type: 'color', default: '#BBBBBB'},\n buttonHighlightColor: {type: 'color', default: '#7A7A7A'},\n model: {default: true},\n orientationOffset: {type: 'vec3'},\n armModel: {default: true}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX,\n this.data.hand ? {hand: this.data.hand} : {});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n el.setAttribute('tracked-controls', {\n armModel: data.armModel,\n hand: data.hand,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset\n });\n if (!this.data.model) { return; }\n this.el.setAttribute('gltf-model', OCULUS_GO_CONTROLLER_MODEL_URL);\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n // No need for onButtonChanged, since Oculus Go controller has no analog buttons.\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n\n if (!this.data.model) { return; }\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.trigger = controllerObject3D.getObjectByName('oculus_go_button_trigger');\n buttonMeshes.trackpad = controllerObject3D.getObjectByName('oculus_go_touchpad');\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var buttonMeshes = this.buttonMeshes;\n if (!buttonMeshes || !buttonMeshes[buttonName]) { return; }\n var color;\n var button;\n switch (state) {\n case 'down':\n color = this.data.buttonHighlightColor;\n break;\n case 'touchstart':\n color = this.data.buttonTouchedColor;\n break;\n default:\n color = this.data.buttonColor;\n }\n button = buttonMeshes[buttonName];\n button.material.color.set(color);\n this.rendererSystem.applyColorCorrection(button.material.color);\n }\n});\n", "var bind = require('../utils/bind');\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar isOculusBrowser = require('../utils/').device.isOculusBrowser();\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'oculus-touch';\nvar GAMEPAD_ID_WEBVR = 'Oculus Touch';\n\n// Prefix for Gen1 and Gen2 Oculus Touch Controllers.\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n// First generation model URL.\nvar TOUCH_CONTROLLER_MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/oculus/oculus-touch-controller-';\n// For now the generation 2 model is the same as the original until a new one is prepared for upload.\nvar TOUCH_GEN2_CONTROLLER_MODEL_BASE_URL = TOUCH_CONTROLLER_MODEL_BASE_URL;\n\nvar OCULUS_TOUCH_WEBVR = {\n left: {\n modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'left.gltf',\n rayOrigin: {origin: {x: 0.008, y: -0.01, z: 0}, direction: {x: 0, y: -0.8, z: -1}},\n modelPivotOffset: new THREE.Vector3(-0.005, 0.003, -0.055),\n modelPivotRotation: new THREE.Euler(0, 0, 0)\n },\n right: {\n modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'right.gltf',\n rayOrigin: {origin: {x: -0.008, y: -0.01, z: 0}, direction: {x: 0, y: -0.8, z: -1}},\n modelPivotOffset: new THREE.Vector3(0.005, 0.003, -0.055),\n modelPivotRotation: new THREE.Euler(0, 0, 0)\n }\n};\n\nvar OCULUS_TOUCH_WEBXR = {\n left: {\n modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'left.gltf',\n rayOrigin: {origin: {x: 0.002, y: -0.005, z: -0.03}, direction: {x: 0, y: -0.8, z: -1}},\n modelPivotOffset: new THREE.Vector3(-0.005, 0.036, -0.037),\n modelPivotRotation: new THREE.Euler(Math.PI / 4.5, 0, 0)\n },\n right: {\n modelUrl: TOUCH_CONTROLLER_MODEL_BASE_URL + 'right.gltf',\n rayOrigin: {origin: {x: -0.002, y: -0.005, z: -0.03}, direction: {x: 0, y: -0.8, z: -1}},\n modelPivotOffset: new THREE.Vector3(0.005, 0.036, -0.037),\n modelPivotRotation: new THREE.Euler(Math.PI / 4.5, 0, 0)\n }\n};\n\nvar OCULUS_TOUCH_CONFIG = isWebXRAvailable ? OCULUS_TOUCH_WEBXR : OCULUS_TOUCH_WEBVR;\n\nvar CONTROLLER_DEFAULT = 'oculus-touch';\nvar CONTROLLER_PROPERTIES = {\n 'oculus-touch': OCULUS_TOUCH_CONFIG,\n 'oculus-touch-v2': {\n left: {\n modelUrl: TOUCH_GEN2_CONTROLLER_MODEL_BASE_URL + 'gen2-left.gltf',\n rayOrigin: {origin: {x: -0.01, y: 0, z: -0.02}, direction: {x: 0, y: -0.5, z: -1}},\n modelPivotOffset: new THREE.Vector3(0, 0, 0),\n modelPivotRotation: new THREE.Euler(0, 0, 0)\n },\n right: {\n modelUrl: TOUCH_GEN2_CONTROLLER_MODEL_BASE_URL + 'gen2-right.gltf',\n rayOrigin: {origin: {x: 0.01, y: 0, z: -0.02}, direction: {x: 0, y: -0.5, z: -1}},\n modelPivotOffset: new THREE.Vector3(0, 0, 0),\n modelPivotRotation: new THREE.Euler(0, 0, 0)\n }\n }\n};\n\n/**\n * Button indices:\n * 0 - thumbstick (which has separate axismove / thumbstickmoved events)\n * 1 - trigger (with analog value, which goes up to 1)\n * 2 - grip (with analog value, which goes up to 1)\n * 3 - X (left) or A (right)\n * 4 - Y (left) or B (right)\n * 5 - surface (touch only)\n */\nvar INPUT_MAPPING_WEBVR = {\n left: {\n axes: {thumbstick: [0, 1]},\n buttons: ['thumbstick', 'trigger', 'grip', 'xbutton', 'ybutton', 'surface']\n },\n right: {\n axes: {thumbstick: [0, 1]},\n buttons: ['thumbstick', 'trigger', 'grip', 'abutton', 'bbutton', 'surface']\n }\n};\n\n/**\n * Button indices:\n * 0 - trigger\n * 1 - grip\n * 2 - none\n * 3 - thumbstick\n * 4 - X or A button\n * 5 - Y or B button\n * 6 - surface\n *\n * Axis:\n * 0 - none\n * 1 - none\n * 2 - thumbstick\n * 3 - thumbstick\n * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/oculus/oculus-touch.json\n */\nvar INPUT_MAPPING_WEBXR = {\n left: {\n axes: {thumbstick: [2, 3]},\n buttons: ['trigger', 'grip', 'none', 'thumbstick', 'xbutton', 'ybutton', 'surface']\n },\n right: {\n axes: {thumbstick: [2, 3]},\n buttons: ['trigger', 'grip', 'none', 'thumbstick', 'abutton', 'bbutton', 'surface']\n }\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Oculus Touch controls.\n * Interface with Oculus Touch controllers and map Gamepad events to\n * controller buttons: thumbstick, trigger, grip, xbutton, ybutton, surface\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('oculus-touch-controls', {\n schema: {\n hand: {default: 'left'},\n buttonColor: {type: 'color', default: '#999'}, // Off-white.\n buttonTouchColor: {type: 'color', default: '#8AB'},\n buttonHighlightColor: {type: 'color', default: '#2DF'}, // Light blue.\n model: {default: true},\n controllerType: {default: 'auto', oneOf: ['auto', 'oculus-touch', 'oculus-touch-v2']},\n orientationOffset: {type: 'vec3', default: {x: 43, y: 0, z: 0}}\n },\n\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self, self.data.hand); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self, self.data.hand); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self, self.data.hand); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self, self.data.hand); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.previousButtonValues = {};\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('axismove', this.onAxisMoved);\n el.addEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, {\n hand: this.data.hand\n });\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n loadModel: function () {\n var data = this.data;\n if (!data.model) { return; }\n\n // Set the controller display model based on the data passed in.\n this.displayModel = CONTROLLER_PROPERTIES[data.controllerType] || CONTROLLER_PROPERTIES[CONTROLLER_DEFAULT];\n // If the developer is asking for auto-detection, see if the displayName can be retrieved to identify the specific unit.\n // This only works for WebVR currently.\n if (data.controllerType === 'auto') {\n var trackedControlsSystem = this.el.sceneEl.systems['tracked-controls-webvr'];\n if (trackedControlsSystem && trackedControlsSystem.vrDisplay) {\n var displayName = trackedControlsSystem.vrDisplay.displayName;\n // The Oculus Quest uses the updated generation 2 inside-out tracked controllers so update the displayModel.\n if (/^Oculus Quest$/.test(displayName)) {\n this.displayModel = CONTROLLER_PROPERTIES['oculus-touch-v2'];\n }\n }\n if (isOculusBrowser) { this.displayModel = CONTROLLER_PROPERTIES['oculus-touch-v2']; }\n }\n var modelUrl = this.displayModel[data.hand].modelUrl;\n this.el.setAttribute('gltf-model', modelUrl);\n },\n\n injectTrackedControls: function () {\n var data = this.data;\n var webXRId = GAMEPAD_ID_WEBXR;\n var webVRId = data.hand === 'right' ? 'Oculus Touch (Right)' : 'Oculus Touch (Left)';\n var id = isWebXRAvailable ? webXRId : webVRId;\n this.el.setAttribute('tracked-controls', {\n id: id,\n hand: data.hand,\n orientationOffset: data.orientationOffset\n });\n this.loadModel();\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n // Note that due to gamepadconnected event propagation issues, we don't rely on events.\n this.checkIfControllerPresent();\n },\n\n onButtonChanged: function (evt) {\n var button = this.mapping[this.data.hand].buttons[evt.detail.id];\n var buttonMeshes = this.buttonMeshes;\n var analogValue;\n if (!button) { return; }\n\n if (button === 'trigger' || button === 'grip') { analogValue = evt.detail.state.value; }\n\n // Update trigger and/or grip meshes, if any.\n if (buttonMeshes) {\n if (button === 'trigger' && buttonMeshes.trigger) {\n buttonMeshes.trigger.rotation.x = this.originalXRotationTrigger - analogValue * (Math.PI / 26);\n }\n if (button === 'grip' && buttonMeshes.grip) {\n buttonMeshes.grip.position.x = this.originalXPositionGrip + (this.data.hand === 'left' ? -1 : 1) * analogValue * 0.004;\n }\n }\n\n // Pass along changed event with button state, using the buttom mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n\n if (!this.data.model) { return; }\n\n buttonMeshes = this.buttonMeshes = {};\n\n buttonMeshes.grip = controllerObject3D.getObjectByName('buttonHand');\n this.originalXPositionGrip = buttonMeshes.grip.position.x;\n buttonMeshes.thumbstick = controllerObject3D.getObjectByName('stick');\n buttonMeshes.trigger = controllerObject3D.getObjectByName('buttonTrigger');\n this.originalXRotationTrigger = buttonMeshes.trigger.rotation.x;\n buttonMeshes.xbutton = controllerObject3D.getObjectByName('buttonX');\n buttonMeshes.abutton = controllerObject3D.getObjectByName('buttonA');\n buttonMeshes.ybutton = controllerObject3D.getObjectByName('buttonY');\n buttonMeshes.bbutton = controllerObject3D.getObjectByName('buttonB');\n\n // Offset pivot point\n controllerObject3D.position.copy(this.displayModel[this.data.hand].modelPivotOffset);\n controllerObject3D.rotation.copy(this.displayModel[this.data.hand].modelPivotRotation);\n\n this.el.emit('controllermodelready', {\n name: 'oculus-touch-controls',\n model: this.data.model,\n rayOrigin: this.displayModel[this.data.hand].rayOrigin\n });\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping[this.data.hand].axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var button;\n var color = (state === 'up' || state === 'touchend') ? this.data.buttonColor : state === 'touchstart' ? this.data.buttonTouchColor : this.data.buttonHighlightColor;\n var buttonMeshes = this.buttonMeshes;\n if (!this.data.model) { return; }\n if (buttonMeshes && buttonMeshes[buttonName]) {\n button = buttonMeshes[buttonName];\n button.material.color.set(color);\n this.rendererSystem.applyColorCorrection(button.material.color);\n }\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\n\nmodule.exports.Component = registerComponent('position', {\n schema: {type: 'vec3'},\n\n update: function () {\n var object3D = this.el.object3D;\n var data = this.data;\n object3D.position.set(data.x, data.y, data.z);\n },\n\n remove: function () {\n // Pretty much for mixins.\n this.el.object3D.position.set(0, 0, 0);\n }\n});\n", "/* global MutationObserver */\n\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\n\nvar warn = utils.debug('components:raycaster:warn');\n\n// Defines selectors that should be 'safe' for the MutationObserver used to\n// refresh the whitelist. Matches classnames, IDs, and presence of attributes.\n// Selectors for the value of an attribute, like [position=0 2 0], cannot be\n// reliably detected and are therefore disallowed.\nvar OBSERVER_SELECTOR_RE = /^[\\w\\s-.,[\\]#]*$/;\n\n// Configuration for the MutationObserver used to refresh the whitelist.\n// Listens for addition/removal of elements and attributes within the scene.\nvar OBSERVER_CONFIG = {\n childList: true,\n attributes: true,\n subtree: true\n};\n\nvar EVENTS = {\n INTERSECT: 'raycaster-intersected',\n INTERSECTION: 'raycaster-intersection',\n INTERSECT_CLEAR: 'raycaster-intersected-cleared',\n INTERSECTION_CLEAR: 'raycaster-intersection-cleared'\n};\n\n/**\n * Raycaster component.\n *\n * Pass options to three.js Raycaster including which objects to test.\n * Poll for intersections.\n * Emit event on origin entity and on target entity on intersect.\n *\n * @member {array} intersectedEls - List of currently intersected entities.\n * @member {array} objects - Cached list of meshes to intersect.\n * @member {number} prevCheckTime - Previous time intersection was checked. To help interval.\n * @member {object} raycaster - three.js Raycaster.\n */\nmodule.exports.Component = registerComponent('raycaster', {\n schema: {\n autoRefresh: {default: true},\n direction: {type: 'vec3', default: {x: 0, y: 0, z: -1}},\n enabled: {default: true},\n far: {default: 1000},\n interval: {default: 0},\n near: {default: 0},\n objects: {default: ''},\n origin: {type: 'vec3'},\n showLine: {default: false},\n useWorldCoordinates: {default: false}\n },\n\n multiple: true,\n\n init: function () {\n this.clearedIntersectedEls = [];\n this.unitLineEndVec3 = new THREE.Vector3();\n this.intersectedEls = [];\n this.intersections = [];\n this.newIntersectedEls = [];\n this.newIntersections = [];\n this.objects = [];\n this.prevCheckTime = undefined;\n this.prevIntersectedEls = [];\n this.rawIntersections = [];\n this.raycaster = new THREE.Raycaster();\n this.updateOriginDirection();\n this.setDirty = this.setDirty.bind(this);\n this.updateLine = this.updateLine.bind(this);\n this.observer = new MutationObserver(this.setDirty);\n this.dirty = true;\n this.lineEndVec3 = new THREE.Vector3();\n this.otherLineEndVec3 = new THREE.Vector3();\n this.lineData = {end: this.lineEndVec3};\n\n this.getIntersection = this.getIntersection.bind(this);\n this.intersectedDetail = {el: this.el, getIntersection: this.getIntersection};\n this.intersectedClearedDetail = {el: this.el};\n this.intersectionClearedDetail = {clearedEls: this.clearedIntersectedEls};\n this.intersectionDetail = {};\n },\n\n /**\n * Create or update raycaster object.\n */\n update: function (oldData) {\n var data = this.data;\n var el = this.el;\n var raycaster = this.raycaster;\n\n // Set raycaster properties.\n raycaster.far = data.far;\n raycaster.near = data.near;\n\n // Draw line.\n if (data.showLine &&\n (data.far !== oldData.far || data.origin !== oldData.origin ||\n data.direction !== oldData.direction || !oldData.showLine)) {\n // Calculate unit vector for line direction. Can be multiplied via scalar to performantly\n // adjust line length.\n this.unitLineEndVec3.copy(data.origin).add(data.direction).normalize();\n this.drawLine();\n }\n\n if (!data.showLine && oldData.showLine) {\n el.removeAttribute('line');\n }\n\n if (data.objects !== oldData.objects && !OBSERVER_SELECTOR_RE.test(data.objects)) {\n warn('[raycaster] Selector \"' + data.objects +\n '\" may not update automatically with DOM changes.');\n }\n\n if (!data.objects) {\n warn('[raycaster] For performance, please define raycaster.objects when using ' +\n 'raycaster or cursor components to whitelist which entities to intersect with. ' +\n 'e.g., raycaster=\"objects: [data-raycastable]\".');\n }\n\n if (data.autoRefresh !== oldData.autoRefresh && el.isPlaying) {\n data.autoRefresh\n ? this.addEventListeners()\n : this.removeEventListeners();\n }\n\n if (oldData.enabled && !data.enabled) { this.clearAllIntersections(); }\n\n this.setDirty();\n },\n\n play: function () {\n this.addEventListeners();\n },\n\n pause: function () {\n this.removeEventListeners();\n },\n\n remove: function () {\n if (this.data.showLine) {\n this.el.removeAttribute('line');\n }\n this.clearAllIntersections();\n },\n\n addEventListeners: function () {\n if (!this.data.autoRefresh) { return; }\n this.observer.observe(this.el.sceneEl, OBSERVER_CONFIG);\n this.el.sceneEl.addEventListener('object3dset', this.setDirty);\n this.el.sceneEl.addEventListener('object3dremove', this.setDirty);\n },\n\n removeEventListeners: function () {\n this.observer.disconnect();\n this.el.sceneEl.removeEventListener('object3dset', this.setDirty);\n this.el.sceneEl.removeEventListener('object3dremove', this.setDirty);\n },\n\n /**\n * Mark the object list as dirty, to be refreshed before next raycast.\n */\n setDirty: function () {\n this.dirty = true;\n },\n\n /**\n * Update list of objects to test for intersection.\n */\n refreshObjects: function () {\n var data = this.data;\n var els;\n\n // If objects not defined, intersect with everything.\n els = data.objects\n ? this.el.sceneEl.querySelectorAll(data.objects)\n : this.el.sceneEl.querySelectorAll('*');\n this.objects = this.flattenObject3DMaps(els);\n this.dirty = false;\n },\n\n /**\n * Check for intersections and cleared intersections on an interval.\n */\n tick: function (time) {\n var data = this.data;\n var prevCheckTime = this.prevCheckTime;\n\n if (!data.enabled) { return; }\n\n // Only check for intersection if interval time has passed.\n if (prevCheckTime && (time - prevCheckTime < data.interval)) { return; }\n\n // Update check time.\n this.prevCheckTime = time;\n this.checkIntersections();\n },\n\n /**\n * Raycast for intersections and emit events for current and cleared inersections.\n */\n checkIntersections: function () {\n var clearedIntersectedEls = this.clearedIntersectedEls;\n var el = this.el;\n var data = this.data;\n var i;\n var intersectedEls = this.intersectedEls;\n var intersection;\n var intersections = this.intersections;\n var newIntersectedEls = this.newIntersectedEls;\n var newIntersections = this.newIntersections;\n var prevIntersectedEls = this.prevIntersectedEls;\n var rawIntersections = this.rawIntersections;\n\n // Refresh the object whitelist if needed.\n if (this.dirty) { this.refreshObjects(); }\n\n // Store old previously intersected entities.\n copyArray(this.prevIntersectedEls, this.intersectedEls);\n\n // Raycast.\n this.updateOriginDirection();\n rawIntersections.length = 0;\n this.raycaster.intersectObjects(this.objects, true, rawIntersections);\n\n // Only keep intersections against objects that have a reference to an entity.\n intersections.length = 0;\n intersectedEls.length = 0;\n for (i = 0; i < rawIntersections.length; i++) {\n intersection = rawIntersections[i];\n // Don't intersect with own line.\n if (data.showLine && intersection.object === el.getObject3D('line')) {\n continue;\n }\n if (intersection.object.el) {\n intersections.push(intersection);\n intersectedEls.push(intersection.object.el);\n }\n }\n\n // Get newly intersected entities.\n newIntersections.length = 0;\n newIntersectedEls.length = 0;\n for (i = 0; i < intersections.length; i++) {\n if (prevIntersectedEls.indexOf(intersections[i].object.el) === -1) {\n newIntersections.push(intersections[i]);\n newIntersectedEls.push(intersections[i].object.el);\n }\n }\n\n // Emit intersection cleared on both entities per formerly intersected entity.\n clearedIntersectedEls.length = 0;\n for (i = 0; i < prevIntersectedEls.length; i++) {\n if (intersectedEls.indexOf(prevIntersectedEls[i]) !== -1) { continue; }\n prevIntersectedEls[i].emit(EVENTS.INTERSECT_CLEAR,\n this.intersectedClearedDetail);\n clearedIntersectedEls.push(prevIntersectedEls[i]);\n }\n if (clearedIntersectedEls.length) {\n el.emit(EVENTS.INTERSECTION_CLEAR, this.intersectionClearedDetail);\n }\n\n // Emit intersected on intersected entity per intersected entity.\n for (i = 0; i < newIntersectedEls.length; i++) {\n newIntersectedEls[i].emit(EVENTS.INTERSECT, this.intersectedDetail);\n }\n\n // Emit all intersections at once on raycasting entity.\n if (newIntersections.length) {\n this.intersectionDetail.els = newIntersectedEls;\n this.intersectionDetail.intersections = newIntersections;\n el.emit(EVENTS.INTERSECTION, this.intersectionDetail);\n }\n\n // Update line length.\n if (data.showLine) { setTimeout(this.updateLine); }\n },\n\n updateLine: function () {\n var el = this.el;\n var intersections = this.intersections;\n var lineLength;\n\n if (intersections.length) {\n if (intersections[0].object.el === el && intersections[1]) {\n lineLength = intersections[1].distance;\n } else {\n lineLength = intersections[0].distance;\n }\n }\n this.drawLine(lineLength);\n },\n\n /**\n * Return the most recent intersection details for a given entity, if any.\n * @param {AEntity} el\n * @return {Object}\n */\n getIntersection: function (el) {\n var i;\n var intersection;\n for (i = 0; i < this.intersections.length; i++) {\n intersection = this.intersections[i];\n if (intersection.object.el === el) { return intersection; }\n }\n return null;\n },\n\n /**\n * Update origin and direction of raycaster using entity transforms and supplied origin or\n * direction offsets.\n */\n updateOriginDirection: (function () {\n var direction = new THREE.Vector3();\n var originVec3 = new THREE.Vector3();\n\n // Closure to make quaternion/vector3 objects private.\n return function updateOriginDirection () {\n var el = this.el;\n var data = this.data;\n\n if (data.useWorldCoordinates) {\n this.raycaster.set(data.origin, data.direction);\n return;\n }\n\n // Grab the position and rotation. (As a side effect, this updates el.object3D.matrixWorld.)\n el.object3D.getWorldPosition(originVec3);\n\n // If non-zero origin, translate the origin into world space.\n if (data.origin.x !== 0 || data.origin.y !== 0 || data.origin.z !== 0) {\n originVec3 = el.object3D.localToWorld(originVec3.copy(data.origin));\n }\n\n // three.js raycaster direction is relative to 0, 0, 0 NOT the origin / offset we\n // provide. Apply the offset to the direction, then rotation from the object,\n // and normalize.\n direction.copy(data.direction).transformDirection(el.object3D.matrixWorld).normalize();\n\n // Apply offset and direction, in world coordinates.\n this.raycaster.set(originVec3, direction);\n };\n })(),\n\n /**\n * Create or update line to give raycaster visual representation.\n * Customize the line through through line component.\n * We draw the line in the raycaster component to customize the line to the\n * raycaster's origin, direction, and far.\n *\n * Unlike the raycaster, we create the line as a child of the object. The line will\n * be affected by the transforms of the objects, so we don't have to calculate transforms\n * like we do with the raycaster.\n *\n * @param {number} length - Length of line. Pass in to shorten the line to the intersection\n * point. If not provided, length will default to the max length, `raycaster.far`.\n */\n drawLine: function (length) {\n var data = this.data;\n var el = this.el;\n var endVec3;\n\n // Switch each time vector so line update triggered and to avoid unnecessary vector clone.\n endVec3 = this.lineData.end === this.lineEndVec3\n ? this.otherLineEndVec3\n : this.lineEndVec3;\n\n // Treat Infinity as 1000m for the line.\n if (length === undefined) {\n length = data.far === Infinity ? 1000 : data.far;\n }\n\n // Update the length of the line if given. `unitLineEndVec3` is the direction\n // given by data.direction, then we apply a scalar to give it a length.\n this.lineData.start = data.origin;\n this.lineData.end = endVec3.copy(this.unitLineEndVec3).multiplyScalar(length);\n el.setAttribute('line', this.lineData);\n },\n\n /**\n * Return A-Frame attachments of each element's object3D group (e.g., mesh).\n * Children are flattened by one level, removing the THREE.Group wrapper,\n * so that non-recursive raycasting remains useful.\n *\n * Only push children defined as component attachemnts (e.g., setObject3D),\n * NOT actual children in the scene graph hierarchy.\n *\n * @param {Array} els\n * @return {Array}\n */\n flattenObject3DMaps: function (els) {\n var key;\n var i;\n var objects = this.objects;\n\n // Push meshes and other attachments onto list of objects to intersect.\n objects.length = 0;\n for (i = 0; i < els.length; i++) {\n if (els[i].isEntity && els[i].object3D) {\n for (key in els[i].object3DMap) {\n objects.push(els[i].getObject3D(key));\n }\n }\n }\n\n return objects;\n },\n\n clearAllIntersections: function () {\n var i;\n for (i = 0; i < this.intersectedEls.length; i++) {\n this.intersectedEls[i].emit(EVENTS.INTERSECT_CLEAR,\n this.intersectedClearedDetail);\n }\n copyArray(this.clearedIntersectedEls, this.intersectedEls);\n this.intersectedEls.length = 0;\n this.intersections.length = 0;\n this.el.emit(EVENTS.INTERSECTION_CLEAR, this.intersectionClearedDetail);\n }\n});\n\n/**\n * Copy contents of one array to another without allocating new array.\n */\nfunction copyArray (a, b) {\n var i;\n a.length = b.length;\n for (i = 0; i < b.length; i++) {\n a[i] = b[i];\n }\n}\n", @@ -331,14 +333,14 @@ "var component = require('../core/component');\nvar THREE = require('../lib/three');\nvar bind = require('../utils/bind');\nvar registerComponent = component.registerComponent;\n\n/**\n * Shadow component.\n *\n * When applied to an entity, that entity's geometry and any descendants will cast or receive\n * shadows as specified by the `cast` and `receive` properties.\n */\nmodule.exports.Component = registerComponent('shadow', {\n schema: {\n cast: {default: true},\n receive: {default: true}\n },\n\n init: function () {\n this.onMeshChanged = bind(this.update, this);\n this.el.addEventListener('object3dset', this.onMeshChanged);\n this.system.setShadowMapEnabled(true);\n },\n\n update: function () {\n var data = this.data;\n this.updateDescendants(data.cast, data.receive);\n },\n\n remove: function () {\n var el = this.el;\n el.removeEventListener('object3dset', this.onMeshChanged);\n this.updateDescendants(false, false);\n },\n\n updateDescendants: function (cast, receive) {\n var sceneEl = this.el.sceneEl;\n this.el.object3D.traverse(function (node) {\n if (!(node instanceof THREE.Mesh)) { return; }\n\n node.castShadow = cast;\n node.receiveShadow = receive;\n\n // If scene has already rendered, materials must be updated.\n if (sceneEl.hasLoaded && node.material) {\n var materials = Array.isArray(node.material) ? node.material : [node.material];\n for (var i = 0; i < materials.length; i++) {\n materials[i].needsUpdate = true;\n }\n }\n });\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar debug = require('../utils/debug');\nvar THREE = require('../lib/three');\n\nvar warn = debug('components:sound:warn');\n\n/**\n * Sound component.\n */\nmodule.exports.Component = registerComponent('sound', {\n schema: {\n autoplay: {default: false},\n distanceModel: {default: 'inverse', oneOf: ['linear', 'inverse', 'exponential']},\n loop: {default: false},\n maxDistance: {default: 10000},\n on: {default: ''},\n poolSize: {default: 1},\n positional: {default: true},\n refDistance: {default: 1},\n rolloffFactor: {default: 1},\n src: {type: 'audio'},\n volume: {default: 1}\n },\n\n multiple: true,\n\n init: function () {\n var self = this;\n\n this.listener = null;\n this.audioLoader = new THREE.AudioLoader();\n this.pool = new THREE.Group();\n this.loaded = false;\n this.mustPlay = false;\n\n // Don't pass evt because playSound takes a function as parameter.\n this.playSoundBound = function () { self.playSound(); };\n },\n\n update: function (oldData) {\n var data = this.data;\n var i;\n var sound;\n var srcChanged = data.src !== oldData.src;\n\n // Create new sound if not yet created or changing `src`.\n if (srcChanged) {\n if (!data.src) { return; }\n this.setupSound();\n }\n\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n if (data.positional) {\n sound.setDistanceModel(data.distanceModel);\n sound.setMaxDistance(data.maxDistance);\n sound.setRefDistance(data.refDistance);\n sound.setRolloffFactor(data.rolloffFactor);\n }\n sound.setLoop(data.loop);\n sound.setVolume(data.volume);\n sound.isPaused = false;\n }\n\n if (data.on !== oldData.on) {\n this.updateEventListener(oldData.on);\n }\n\n // All sound values set. Load in `src`.\n if (srcChanged) {\n var self = this;\n\n this.loaded = false;\n this.audioLoader.load(data.src, function (buffer) {\n for (i = 0; i < self.pool.children.length; i++) {\n sound = self.pool.children[i];\n sound.setBuffer(buffer);\n }\n self.loaded = true;\n\n // Remove this key from cache, otherwise we can't play it again\n THREE.Cache.remove(data.src);\n if (self.data.autoplay || self.mustPlay) { self.playSound(); }\n self.el.emit('sound-loaded', self.evtDetail, false);\n });\n }\n },\n\n pause: function () {\n this.stopSound();\n this.removeEventListener();\n },\n\n play: function () {\n if (this.data.autoplay) { this.playSound(); }\n this.updateEventListener();\n },\n\n remove: function () {\n var i;\n var sound;\n\n this.removeEventListener();\n\n if (this.el.getObject3D(this.attrName)) {\n this.el.removeObject3D(this.attrName);\n }\n\n try {\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n sound.disconnect();\n }\n } catch (e) {\n // disconnect() will throw if it was never connected initially.\n warn('Audio source not properly disconnected');\n }\n },\n\n /**\n * Update listener attached to the user defined on event.\n */\n updateEventListener: function (oldEvt) {\n var el = this.el;\n if (oldEvt) { el.removeEventListener(oldEvt, this.playSoundBound); }\n el.addEventListener(this.data.on, this.playSoundBound);\n },\n\n removeEventListener: function () {\n this.el.removeEventListener(this.data.on, this.playSoundBound);\n },\n\n /**\n * Removes current sound object, creates new sound object, adds to entity.\n *\n * @returns {object} sound\n */\n setupSound: function () {\n var el = this.el;\n var i;\n var sceneEl = el.sceneEl;\n var self = this;\n var sound;\n\n if (this.pool.children.length > 0) {\n this.stopSound();\n el.removeObject3D('sound');\n }\n\n // Only want one AudioListener. Cache it on the scene.\n var listener = this.listener = sceneEl.audioListener || new THREE.AudioListener();\n sceneEl.audioListener = listener;\n\n if (sceneEl.camera) {\n sceneEl.camera.add(listener);\n }\n\n // Wait for camera if necessary.\n sceneEl.addEventListener('camera-set-active', function (evt) {\n evt.detail.cameraEl.getObject3D('camera').add(listener);\n });\n\n // Create [poolSize] audio instances and attach them to pool\n this.pool = new THREE.Group();\n for (i = 0; i < this.data.poolSize; i++) {\n sound = this.data.positional\n ? new THREE.PositionalAudio(listener)\n : new THREE.Audio(listener);\n this.pool.add(sound);\n }\n el.setObject3D(this.attrName, this.pool);\n\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n sound.onEnded = function () {\n this.isPlaying = false;\n self.el.emit('sound-ended', self.evtDetail, false);\n };\n }\n },\n\n /**\n * Pause all the sounds in the pool.\n */\n pauseSound: function () {\n var i;\n var sound;\n\n this.isPlaying = false;\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n if (!sound.source || !sound.source.buffer || !sound.isPlaying || sound.isPaused) {\n continue;\n }\n sound.isPaused = true;\n sound.pause();\n }\n },\n\n /**\n * Look for an unused sound in the pool and play it if found.\n */\n playSound: function (processSound) {\n var found;\n var i;\n var sound;\n\n if (!this.loaded) {\n warn('Sound not loaded yet. It will be played once it finished loading');\n this.mustPlay = true;\n return;\n }\n\n found = false;\n this.isPlaying = true;\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n if (!sound.isPlaying && sound.buffer && !found) {\n if (processSound) { processSound(sound); }\n sound.play();\n sound.isPaused = false;\n found = true;\n continue;\n }\n }\n\n if (!found) {\n warn('All the sounds are playing. If you need to play more sounds simultaneously ' +\n 'consider increasing the size of pool with the `poolSize` attribute.', this.el);\n return;\n }\n\n this.mustPlay = false;\n },\n\n /**\n * Stop all the sounds in the pool.\n */\n stopSound: function () {\n var i;\n var sound;\n this.isPlaying = false;\n for (i = 0; i < this.pool.children.length; i++) {\n sound = this.pool.children[i];\n if (!sound.source || !sound.source.buffer) { return; }\n sound.stop();\n }\n }\n});\n", "var createTextGeometry = require('three-bmfont-text');\nvar loadBMFont = require('load-bmfont');\n\nvar registerComponent = require('../core/component').registerComponent;\nvar coreShader = require('../core/shader');\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\n\nvar error = utils.debug('components:text:error');\nvar shaders = coreShader.shaders;\nvar warn = utils.debug('components:text:warn');\n\n// 1 to match other A-Frame default widths.\nvar DEFAULT_WIDTH = 1;\n\n// @bryik set anisotropy to 16. Improves look of large amounts of text when viewed from angle.\nvar MAX_ANISOTROPY = 16;\n\nvar FONT_BASE_URL = 'https://cdn.aframe.io/fonts/';\nvar FONTS = {\n aileronsemibold: FONT_BASE_URL + 'Aileron-Semibold.fnt',\n dejavu: FONT_BASE_URL + 'DejaVu-sdf.fnt',\n exo2bold: FONT_BASE_URL + 'Exo2Bold.fnt',\n exo2semibold: FONT_BASE_URL + 'Exo2SemiBold.fnt',\n kelsonsans: FONT_BASE_URL + 'KelsonSans.fnt',\n monoid: FONT_BASE_URL + 'Monoid.fnt',\n mozillavr: FONT_BASE_URL + 'mozillavr.fnt',\n roboto: FONT_BASE_URL + 'Roboto-msdf.json',\n sourcecodepro: FONT_BASE_URL + 'SourceCodePro.fnt'\n};\nvar MSDF_FONTS = ['roboto'];\nvar DEFAULT_FONT = 'roboto';\nmodule.exports.FONTS = FONTS;\n\nvar cache = new PromiseCache();\nvar fontWidthFactors = {};\nvar textures = {};\n\n// Regular expression for detecting a URLs with a protocol prefix.\nvar protocolRe = /^\\w+:/;\n\n/**\n * SDF-based text component.\n * Based on https://github.com/Jam3/three-bmfont-text.\n *\n * All the stock fonts are for the `sdf` registered shader, an improved version of jam3's\n * original `sdf` shader.\n */\nmodule.exports.Component = registerComponent('text', {\n multiple: true,\n\n schema: {\n align: {type: 'string', default: 'left', oneOf: ['left', 'right', 'center']},\n alphaTest: {default: 0.5},\n // `anchor` defaults to center to match geometries.\n anchor: {default: 'center', oneOf: ['left', 'right', 'center', 'align']},\n baseline: {default: 'center', oneOf: ['top', 'center', 'bottom']},\n color: {type: 'color', default: '#FFF'},\n font: {type: 'string', default: DEFAULT_FONT},\n // `fontImage` defaults to the font name as a .png (e.g., mozillavr.fnt -> mozillavr.png).\n fontImage: {type: 'string'},\n // `height` has no default, will be populated at layout.\n height: {type: 'number'},\n letterSpacing: {type: 'number', default: 0},\n // `lineHeight` defaults to font's `lineHeight` value.\n lineHeight: {type: 'number'},\n // `negate` must be true for fonts generated with older versions of msdfgen (white background).\n negate: {type: 'boolean', default: true},\n opacity: {type: 'number', default: 1.0},\n shader: {default: 'sdf', oneOf: shaders},\n side: {default: 'front', oneOf: ['front', 'back', 'double']},\n tabSize: {default: 4},\n transparent: {default: true},\n value: {type: 'string'},\n whiteSpace: {default: 'normal', oneOf: ['normal', 'pre', 'nowrap']},\n // `width` defaults to geometry width if present, else `DEFAULT_WIDTH`.\n width: {type: 'number'},\n // `wrapCount` units are about one default font character. Wrap roughly at this number.\n wrapCount: {type: 'number', default: 40},\n // `wrapPixels` will wrap using bmfont pixel units (e.g., dejavu's is 32 pixels).\n wrapPixels: {type: 'number'},\n // `xOffset` to add padding.\n xOffset: {type: 'number', default: 0},\n // `yOffset` to adjust generated fonts from tools that may have incorrect metrics.\n yOffset: {type: 'number', default: 0},\n // `zOffset` will provide a small z offset to avoid z-fighting.\n zOffset: {type: 'number', default: 0.001}\n },\n\n init: function () {\n this.shaderData = {};\n this.geometry = createTextGeometry();\n this.createOrUpdateMaterial();\n this.mesh = new THREE.Mesh(this.geometry, this.material);\n this.el.setObject3D(this.attrName, this.mesh);\n },\n\n update: function (oldData) {\n var data = this.data;\n var font = this.currentFont;\n\n if (textures[data.font]) {\n this.texture = textures[data.font];\n } else {\n // Create texture per font.\n this.texture = textures[data.font] = new THREE.Texture();\n this.texture.anisotropy = MAX_ANISOTROPY;\n }\n\n // Update material.\n this.createOrUpdateMaterial();\n\n // New font. `updateFont` will later change data and layout.\n if (oldData.font !== data.font) {\n this.updateFont();\n return;\n }\n\n // Update geometry and layout.\n if (font) {\n this.updateGeometry(this.geometry, font);\n this.updateLayout();\n }\n },\n\n /**\n * Clean up geometry, material, texture, mesh, objects.\n */\n remove: function () {\n this.geometry.dispose();\n this.geometry = null;\n this.el.removeObject3D(this.attrName);\n this.material.dispose();\n this.material = null;\n this.texture.dispose();\n this.texture = null;\n if (this.shaderObject) {\n delete this.shaderObject;\n }\n },\n\n /**\n * Update the shader of the material.\n */\n createOrUpdateMaterial: function () {\n var data = this.data;\n var hasChangedShader;\n var material = this.material;\n var NewShader;\n var shaderData = this.shaderData;\n var shaderName;\n\n // Infer shader if using a stock font (or from `-msdf` filename convention).\n shaderName = data.shader;\n if (MSDF_FONTS.indexOf(data.font) !== -1 || data.font.indexOf('-msdf.') >= 0) {\n shaderName = 'msdf';\n } else if (data.font in FONTS && MSDF_FONTS.indexOf(data.font) === -1) {\n shaderName = 'sdf';\n }\n\n hasChangedShader = (this.shaderObject && this.shaderObject.name) !== shaderName;\n\n shaderData.alphaTest = data.alphaTest;\n shaderData.color = data.color;\n shaderData.map = this.texture;\n shaderData.opacity = data.opacity;\n shaderData.side = parseSide(data.side);\n shaderData.transparent = data.transparent;\n shaderData.negate = data.negate;\n\n // Shader has not changed, do an update.\n if (!hasChangedShader) {\n // Update shader material.\n this.shaderObject.update(shaderData);\n // Apparently, was not set on `init` nor `update`.\n material.transparent = shaderData.transparent;\n material.side = shaderData.side;\n return;\n }\n\n // Shader has changed. Create a shader material.\n NewShader = createShader(this.el, shaderName, shaderData);\n this.material = NewShader.material;\n this.shaderObject = NewShader.shader;\n\n // Set new shader material.\n this.material.side = shaderData.side;\n if (this.mesh) { this.mesh.material = this.material; }\n },\n\n /**\n * Load font for geometry, load font image for material, and apply.\n */\n updateFont: function () {\n var data = this.data;\n var el = this.el;\n var fontSrc;\n var geometry = this.geometry;\n var self = this;\n\n if (!data.font) { warn('No font specified. Using the default font.'); }\n\n // Make invisible during font swap.\n this.mesh.visible = false;\n\n // Look up font URL to use, and perform cached load.\n fontSrc = this.lookupFont(data.font || DEFAULT_FONT) || data.font;\n cache.get(fontSrc, function doLoadFont () {\n return loadFont(fontSrc, data.yOffset);\n }).then(function setFont (font) {\n var fontImgSrc;\n\n if (font.pages.length !== 1) {\n throw new Error('Currently only single-page bitmap fonts are supported.');\n }\n\n if (!fontWidthFactors[fontSrc]) {\n font.widthFactor = fontWidthFactors[font] = computeFontWidthFactor(font);\n }\n\n // Update geometry given font metrics.\n self.updateGeometry(geometry, font);\n\n // Set font and update layout.\n self.currentFont = font;\n self.updateLayout();\n\n // Look up font image URL to use, and perform cached load.\n fontImgSrc = self.getFontImageSrc();\n cache.get(fontImgSrc, function () {\n return loadTexture(fontImgSrc);\n }).then(function (image) {\n // Make mesh visible and apply font image as texture.\n var texture = self.texture;\n texture.image = image;\n texture.needsUpdate = true;\n textures[data.font] = texture;\n self.texture = texture;\n self.mesh.visible = true;\n el.emit('textfontset', {font: data.font, fontObj: font});\n }).catch(function (err) {\n error(err.message);\n error(err.stack);\n });\n }).catch(function (err) {\n error(err.message);\n error(err.stack);\n });\n },\n\n getFontImageSrc: function () {\n if (this.data.fontImage) { return this.data.fontImage; }\n var fontSrc = this.lookupFont(this.data.font || DEFAULT_FONT) || this.data.font;\n var imageSrc = this.currentFont.pages[0];\n // If the image URL contains a non-HTTP(S) protocol, assume it's an absolute\n // path on disk and try to infer the path from the font source instead.\n if (imageSrc.match(protocolRe) && imageSrc.indexOf('http') !== 0) {\n return fontSrc.replace(/(\\.fnt)|(\\.json)/, '.png');\n }\n return THREE.LoaderUtils.extractUrlBase(fontSrc) + imageSrc;\n },\n\n /**\n * Update layout with anchor, alignment, baseline, and considering any meshes.\n */\n updateLayout: function () {\n var anchor;\n var baseline;\n var el = this.el;\n var data = this.data;\n var geometry = this.geometry;\n var geometryComponent;\n var height;\n var layout;\n var mesh = this.mesh;\n var textRenderWidth;\n var textScale;\n var width;\n var x;\n var y;\n\n if (!geometry.layout) { return; }\n\n // Determine width to use (defined width, geometry's width, or default width).\n geometryComponent = el.getAttribute('geometry');\n width = data.width || (geometryComponent && geometryComponent.width) || DEFAULT_WIDTH;\n\n // Determine wrap pixel count. Either specified or by experimental fudge factor.\n // Note that experimental factor will never be correct for variable width fonts.\n textRenderWidth = computeWidth(data.wrapPixels, data.wrapCount,\n this.currentFont.widthFactor);\n textScale = width / textRenderWidth;\n\n // Determine height to use.\n layout = geometry.layout;\n height = textScale * (layout.height + layout.descender);\n\n // Update geometry dimensions to match text layout if width and height are set to 0.\n // For example, scales a plane to fit text.\n if (geometryComponent && geometryComponent.primitive === 'plane') {\n if (!geometryComponent.width) { el.setAttribute('geometry', 'width', width); }\n if (!geometryComponent.height) { el.setAttribute('geometry', 'height', height); }\n }\n\n // Calculate X position to anchor text left, center, or right.\n anchor = data.anchor === 'align' ? data.align : data.anchor;\n if (anchor === 'left') {\n x = 0;\n } else if (anchor === 'right') {\n x = -1 * layout.width;\n } else if (anchor === 'center') {\n x = -1 * layout.width / 2;\n } else {\n throw new TypeError('Invalid text.anchor property value', anchor);\n }\n\n // Calculate Y position to anchor text top, center, or bottom.\n baseline = data.baseline;\n if (baseline === 'bottom') {\n y = 0;\n } else if (baseline === 'top') {\n y = -1 * layout.height + layout.ascender;\n } else if (baseline === 'center') {\n y = -1 * layout.height / 2;\n } else {\n throw new TypeError('Invalid text.baseline property value', baseline);\n }\n\n // Position and scale mesh to apply layout.\n mesh.position.x = x * textScale + data.xOffset;\n mesh.position.y = y * textScale;\n // Place text slightly in front to avoid Z-fighting.\n mesh.position.z = data.zOffset;\n mesh.scale.set(textScale, -1 * textScale, textScale);\n },\n\n /**\n * Grab font from the constant.\n * Set as a method for test stubbing purposes.\n */\n lookupFont: function (key) {\n return FONTS[key];\n },\n\n /**\n * Update the text geometry using `three-bmfont-text.update`.\n */\n updateGeometry: (function () {\n var geometryUpdateBase = {};\n var geometryUpdateData = {};\n var newLineRegex = /\\\\n/g;\n var tabRegex = /\\\\t/g;\n\n return function (geometry, font) {\n var data = this.data;\n\n geometryUpdateData.font = font;\n geometryUpdateData.lineHeight = data.lineHeight && isFinite(data.lineHeight)\n ? data.lineHeight\n : font.common.lineHeight;\n geometryUpdateData.text = data.value.toString().replace(newLineRegex, '\\n')\n .replace(tabRegex, '\\t');\n geometryUpdateData.width = computeWidth(data.wrapPixels, data.wrapCount,\n font.widthFactor);\n geometry.update(utils.extend(geometryUpdateBase, data, geometryUpdateData));\n };\n })()\n});\n\n/**\n * Due to using negative scale, we return the opposite side specified.\n * https://github.com/mrdoob/three.js/pull/12787/\n */\nfunction parseSide (side) {\n switch (side) {\n case 'back': {\n return THREE.FrontSide;\n }\n case 'double': {\n return THREE.DoubleSide;\n }\n default: {\n return THREE.BackSide;\n }\n }\n}\n\n/**\n * @returns {Promise}\n */\nfunction loadFont (src, yOffset) {\n return new Promise(function (resolve, reject) {\n loadBMFont(src, function (err, font) {\n if (err) {\n error('Error loading font', src);\n reject(err);\n return;\n }\n\n // Fix negative Y offsets for Roboto MSDF font from tool. Experimentally determined.\n if (src.indexOf('/Roboto-msdf.json') >= 0) { yOffset = 30; }\n if (yOffset) { font.chars.map(function doOffset (ch) { ch.yoffset += yOffset; }); }\n\n resolve(font);\n });\n });\n}\n\n/**\n * @returns {Promise}\n */\nfunction loadTexture (src) {\n return new Promise(function (resolve, reject) {\n new THREE.ImageLoader().load(src, function (image) {\n resolve(image);\n }, undefined, function () {\n error('Error loading font image', src);\n reject(null);\n });\n });\n}\n\nfunction createShader (el, shaderName, data) {\n var shader;\n var shaderObject;\n\n // Set up Shader.\n shaderObject = new shaders[shaderName].Shader();\n shaderObject.el = el;\n shaderObject.init(data);\n shaderObject.update(data);\n\n // Get material.\n shader = shaderObject.material;\n // Apparently, was not set on `init` nor `update`.\n shader.transparent = data.transparent;\n\n return {\n material: shader,\n shader: shaderObject\n };\n}\n\n/**\n * Determine wrap pixel count. Either specified or by experimental fudge factor.\n * Note that experimental factor will never be correct for variable width fonts.\n */\nfunction computeWidth (wrapPixels, wrapCount, widthFactor) {\n return wrapPixels || ((0.5 + wrapCount) * widthFactor);\n}\n\n/**\n * Compute default font width factor to use.\n */\nfunction computeFontWidthFactor (font) {\n var sum = 0;\n var digitsum = 0;\n var digits = 0;\n font.chars.map(function (ch) {\n sum += ch.xadvance;\n if (ch.id >= 48 && ch.id <= 57) {\n digits++;\n digitsum += ch.xadvance;\n }\n });\n return digits ? digitsum / digits : sum / font.chars.length;\n}\n\n/**\n * Get or create a promise given a key and promise generator.\n * @todo Move to a utility and use in other parts of A-Frame.\n */\nfunction PromiseCache () {\n var cache = this.cache = {};\n\n this.get = function (key, promiseGenerator) {\n if (key in cache) {\n return cache[key];\n }\n cache[key] = promiseGenerator();\n return cache[key];\n };\n}\n", - "var registerComponent = require('../core/component').registerComponent;\nvar controllerUtils = require('../utils/tracked-controls');\nvar DEFAULT_CAMERA_HEIGHT = require('../constants').DEFAULT_CAMERA_HEIGHT;\nvar THREE = require('../lib/three');\n\nvar DEFAULT_HANDEDNESS = require('../constants').DEFAULT_HANDEDNESS;\n// Vector from eyes to elbow (divided by user height).\nvar EYES_TO_ELBOW = {x: 0.175, y: -0.3, z: -0.03};\n// Vector from eyes to elbow (divided by user height).\nvar FOREARM = {x: 0, y: 0, z: -0.175};\n\n// Due to unfortunate name collision, add empty touches array to avoid Daydream error.\nvar EMPTY_DAYDREAM_TOUCHES = {touches: []};\n\nvar EVENTS = {\n AXISMOVE: 'axismove',\n BUTTONCHANGED: 'buttonchanged',\n BUTTONDOWN: 'buttondown',\n BUTTONUP: 'buttonup',\n TOUCHSTART: 'touchstart',\n TOUCHEND: 'touchend'\n};\n\n/**\n * Tracked controls component.\n * Wrap the gamepad API for pose and button states.\n * Select the appropriate controller and apply pose to the entity.\n * Observe button states and emit appropriate events.\n *\n * @property {number} controller - Index of controller in array returned by Gamepad API.\n * Only used if hand property is not set.\n * @property {string} id - Selected controller among those returned by Gamepad API.\n * @property {number} hand - If multiple controllers found with id, choose the one with the\n * given value for hand. If set, we ignore 'controller' property\n */\nmodule.exports.Component = registerComponent('tracked-controls-webvr', {\n schema: {\n autoHide: {default: true},\n controller: {default: 0},\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n idPrefix: {type: 'string', default: ''},\n orientationOffset: {type: 'vec3'},\n // Arm model parameters when not 6DoF.\n armModel: {default: true},\n headElement: {type: 'selector'}\n },\n\n init: function () {\n // Copy variables back to tracked-controls for backwards compatibility.\n // Some 3rd components rely on them.\n this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0];\n this.buttonStates = this.el.components['tracked-controls'].buttonStates = {};\n this.changedAxes = [];\n this.targetControllerNumber = this.data.controller;\n\n this.axisMoveEventDetail = {axis: this.axis, changed: this.changedAxes};\n this.deltaControllerPosition = new THREE.Vector3();\n this.controllerQuaternion = new THREE.Quaternion();\n this.controllerEuler = new THREE.Euler();\n\n this.updateGamepad();\n\n this.buttonEventDetails = {};\n },\n\n tick: function (time, delta) {\n var mesh = this.el.getObject3D('mesh');\n // Update mesh animations.\n if (mesh && mesh.update) { mesh.update(delta / 1000); }\n this.updateGamepad();\n this.updatePose();\n this.updateButtons();\n },\n\n /**\n * Return default user height to use for non-6DOF arm model.\n */\n defaultUserHeight: function () {\n return DEFAULT_CAMERA_HEIGHT;\n },\n\n /**\n * Return head element to use for non-6DOF arm model.\n */\n getHeadElement: function () {\n return this.data.headElement || this.el.sceneEl.camera.el;\n },\n\n /**\n * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`)\n */\n updateGamepad: function () {\n var data = this.data;\n var controller = controllerUtils.findMatchingControllerWebVR(\n this.system.controllers,\n data.id,\n data.idPrefix,\n data.hand,\n data.controller\n );\n\n this.controller = controller;\n // Legacy handle to the controller for old components.\n this.el.components['tracked-controls'].controller = controller;\n\n if (this.data.autoHide) { this.el.object3D.visible = !!this.controller; }\n },\n\n /**\n * Applies an artificial arm model to simulate elbow to wrist positioning\n * based on the orientation of the controller.\n *\n * @param {object} controllerPosition - Existing vector to update with controller position.\n */\n applyArmModel: function (controllerPosition) {\n // Use controllerPosition and deltaControllerPosition to avoid creating variables.\n var controller = this.controller;\n var controllerEuler = this.controllerEuler;\n var controllerQuaternion = this.controllerQuaternion;\n var deltaControllerPosition = this.deltaControllerPosition;\n var hand;\n var headEl;\n var headObject3D;\n var pose;\n var userHeight;\n\n headEl = this.getHeadElement();\n headObject3D = headEl.object3D;\n userHeight = this.defaultUserHeight();\n\n pose = controller.pose;\n hand = (controller ? controller.hand : undefined) || DEFAULT_HANDEDNESS;\n\n // Use camera position as head position.\n controllerPosition.copy(headObject3D.position);\n // Set offset for degenerate \"arm model\" to elbow.\n deltaControllerPosition.set(\n EYES_TO_ELBOW.x * (hand === 'left' ? -1 : hand === 'right' ? 1 : 0),\n EYES_TO_ELBOW.y, // Lower than our eyes.\n EYES_TO_ELBOW.z); // Slightly out in front.\n // Scale offset by user height.\n deltaControllerPosition.multiplyScalar(userHeight);\n // Apply camera Y rotation (not X or Z, so you can look down at your hand).\n deltaControllerPosition.applyAxisAngle(headObject3D.up, headObject3D.rotation.y);\n // Apply rotated offset to position.\n controllerPosition.add(deltaControllerPosition);\n\n // Set offset for degenerate \"arm model\" forearm. Forearm sticking out from elbow.\n deltaControllerPosition.set(FOREARM.x, FOREARM.y, FOREARM.z);\n // Scale offset by user height.\n deltaControllerPosition.multiplyScalar(userHeight);\n // Apply controller X/Y rotation (tilting up/down/left/right is usually moving the arm).\n if (pose.orientation) {\n controllerQuaternion.fromArray(pose.orientation);\n } else {\n controllerQuaternion.copy(headObject3D.quaternion);\n }\n controllerEuler.setFromQuaternion(controllerQuaternion);\n controllerEuler.set(controllerEuler.x, controllerEuler.y, 0);\n deltaControllerPosition.applyEuler(controllerEuler);\n // Apply rotated offset to position.\n controllerPosition.add(deltaControllerPosition);\n },\n\n /**\n * Read pose from controller (from Gamepad API), apply transforms, apply to entity.\n */\n updatePose: function () {\n var controller = this.controller;\n var data = this.data;\n var object3D = this.el.object3D;\n var pose;\n var vrDisplay = this.system.vrDisplay;\n var standingMatrix;\n\n if (!controller) { return; }\n\n // Compose pose from Gamepad.\n pose = controller.pose;\n\n if (pose.position) {\n object3D.position.fromArray(pose.position);\n } else {\n // Controller not 6DOF, apply arm model.\n if (data.armModel) { this.applyArmModel(object3D.position); }\n }\n\n if (pose.orientation) {\n object3D.quaternion.fromArray(pose.orientation);\n }\n\n // Apply transforms, if 6DOF and in VR.\n if (vrDisplay && pose.position) {\n standingMatrix = this.el.sceneEl.renderer.xr.getStandingMatrix();\n object3D.matrix.compose(object3D.position, object3D.quaternion, object3D.scale);\n object3D.matrix.multiplyMatrices(standingMatrix, object3D.matrix);\n object3D.matrix.decompose(object3D.position, object3D.quaternion, object3D.scale);\n }\n\n object3D.rotateX(this.data.orientationOffset.x * THREE.Math.DEG2RAD);\n object3D.rotateY(this.data.orientationOffset.y * THREE.Math.DEG2RAD);\n object3D.rotateZ(this.data.orientationOffset.z * THREE.Math.DEG2RAD);\n },\n\n /**\n * Handle button changes including axes, presses, touches, values.\n */\n updateButtons: function () {\n var buttonState;\n var controller = this.controller;\n var id;\n\n if (!controller) { return; }\n\n // Check every button.\n for (id = 0; id < controller.buttons.length; ++id) {\n // Initialize button state.\n if (!this.buttonStates[id]) {\n this.buttonStates[id] = {pressed: false, touched: false, value: 0};\n }\n if (!this.buttonEventDetails[id]) {\n this.buttonEventDetails[id] = {id: id, state: this.buttonStates[id]};\n }\n\n buttonState = controller.buttons[id];\n this.handleButton(id, buttonState);\n }\n // Check axes.\n this.handleAxes();\n },\n\n /**\n * Handle presses and touches for a single button.\n *\n * @param {number} id - Index of button in Gamepad button array.\n * @param {number} buttonState - Value of button state from 0 to 1.\n * @returns {boolean} Whether button has changed in any way.\n */\n handleButton: function (id, buttonState) {\n var changed;\n changed = this.handlePress(id, buttonState) |\n this.handleTouch(id, buttonState) |\n this.handleValue(id, buttonState);\n if (!changed) { return false; }\n this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false);\n return true;\n },\n\n /**\n * An axis is an array of values from -1 (up, left) to 1 (down, right).\n * Compare each component of the axis to the previous value to determine change.\n *\n * @returns {boolean} Whether axes changed.\n */\n handleAxes: function () {\n var changed = false;\n var controllerAxes = this.controller.axes;\n var i;\n var previousAxis = this.axis;\n var changedAxes = this.changedAxes;\n\n // Check if axis changed.\n this.changedAxes.length = 0;\n for (i = 0; i < controllerAxes.length; ++i) {\n changedAxes.push(previousAxis[i] !== controllerAxes[i]);\n if (changedAxes[i]) { changed = true; }\n }\n if (!changed) { return false; }\n\n this.axis.length = 0;\n for (i = 0; i < controllerAxes.length; i++) {\n this.axis.push(controllerAxes[i]);\n }\n this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false);\n return true;\n },\n\n /**\n * Determine whether a button press has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button press state changed.\n */\n handlePress: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.pressed === previousButtonState.pressed) { return false; }\n\n evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.pressed = buttonState.pressed;\n return true;\n },\n\n /**\n * Determine whether a button touch has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button touch state changed.\n */\n handleTouch: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.touched === previousButtonState.touched) { return false; }\n\n evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND;\n this.el.emit(evtName, this.buttonEventDetails[id], false, EMPTY_DAYDREAM_TOUCHES);\n previousButtonState.touched = buttonState.touched;\n return true;\n },\n\n /**\n * Determine whether a button value has changed.\n *\n * @param {string} id - Id of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button value changed.\n */\n handleValue: function (id, buttonState) {\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.value === previousButtonState.value) { return false; }\n\n previousButtonState.value = buttonState.value;\n return true;\n }\n});\n", - "var controllerUtils = require('../utils/tracked-controls');\nvar registerComponent = require('../core/component').registerComponent;\n\nvar EVENTS = {\n AXISMOVE: 'axismove',\n BUTTONCHANGED: 'buttonchanged',\n BUTTONDOWN: 'buttondown',\n BUTTONUP: 'buttonup',\n TOUCHSTART: 'touchstart',\n TOUCHEND: 'touchend'\n};\n\nmodule.exports.Component = registerComponent('tracked-controls-webxr', {\n schema: {\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n index: {type: 'int', default: -1},\n iterateControllerProfiles: {default: false}\n },\n\n init: function () {\n this.addSessionEventListeners = this.addSessionEventListeners.bind(this);\n this.updateController = this.updateController.bind(this);\n this.emitButtonUpEvent = this.emitButtonUpEvent.bind(this);\n this.emitButtonDownEvent = this.emitButtonDownEvent.bind(this);\n\n this.selectEventDetails = {id: 'trigger', state: {pressed: false}};\n this.buttonEventDetails = {};\n this.buttonStates = this.el.components['tracked-controls'].buttonStates = {};\n this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0];\n this.changedAxes = [];\n this.axisMoveEventDetail = {axis: this.axis, changed: this.changedAxes};\n },\n\n play: function () {\n var sceneEl = this.el.sceneEl;\n this.updateController();\n this.addSessionEventListeners();\n sceneEl.addEventListener('enter-vr', this.addSessionEventListeners);\n sceneEl.addEventListener('controllersupdated', this.updateController);\n },\n\n pause: function () {\n var sceneEl = this.el.sceneEl;\n this.removeSessionEventListeners();\n sceneEl.removeEventListener('enter-vr', this.addSessionEventListeners);\n sceneEl.removeEventListener('controllersupdated', this.updateController);\n },\n\n addSessionEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n if (!sceneEl.xrSession) { return; }\n sceneEl.xrSession.addEventListener('selectstart', this.emitButtonDownEvent);\n sceneEl.xrSession.addEventListener('selectend', this.emitButtonUpEvent);\n },\n\n removeSessionEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n if (!sceneEl.xrSession) { return; }\n sceneEl.xrSession.removeEventListener('selectstart', this.emitButtonDownEvent);\n sceneEl.xrSession.removeEventListener('selectend', this.emitButtonUpEvent);\n },\n\n emitButtonDownEvent: function (evt) {\n if (!this.controller || evt.inputSource.handedness !== this.data.hand) { return; }\n if (this.controller.gamepad) { return; }\n this.selectEventDetails.state.pressed = true;\n this.el.emit('buttondown', this.selectEventDetails);\n this.el.emit('buttonchanged', this.selectEventDetails);\n this.el.emit('triggerdown');\n },\n\n emitButtonUpEvent: function (evt) {\n if (!this.controller || evt.inputSource.handedness !== this.data.hand) { return; }\n if (this.controller.gamepad) { return; }\n this.selectEventDetails.state.pressed = false;\n this.el.emit('buttonup', this.selectEventDetails);\n this.el.emit('buttonchanged', this.selectEventDetails);\n this.el.emit('triggerup');\n },\n\n /**\n * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`)\n */\n updateController: function () {\n this.controller = controllerUtils.findMatchingControllerWebXR(\n this.system.controllers,\n this.data.id,\n this.data.hand,\n this.data.index,\n this.data.iterateControllerProfiles\n );\n // Legacy handle to the controller for old components.\n this.el.components['tracked-controls'].controller = this.controller;\n\n if (this.data.autoHide) { this.el.object3D.visible = !!this.controller; }\n },\n\n tick: function () {\n var sceneEl = this.el.sceneEl;\n if (!this.controller || !sceneEl.frame) { return; }\n this.pose = sceneEl.frame.getPose(this.controller.targetRaySpace, this.system.referenceSpace);\n this.updatePose();\n this.updateButtons();\n },\n\n updatePose: function () {\n var object3D = this.el.object3D;\n var pose = this.pose;\n if (!pose) { return; }\n object3D.matrix.elements = pose.transform.matrix;\n object3D.matrix.decompose(object3D.position, object3D.rotation, object3D.scale);\n },\n\n /**\n * Handle button changes including axes, presses, touches, values.\n */\n updateButtons: function () {\n var buttonState;\n var id;\n var controller = this.controller;\n var gamepad;\n if (!controller || !controller.gamepad) { return; }\n\n gamepad = controller.gamepad;\n // Check every button.\n for (id = 0; id < gamepad.buttons.length; ++id) {\n // Initialize button state.\n if (!this.buttonStates[id]) {\n this.buttonStates[id] = {pressed: false, touched: false, value: 0};\n }\n if (!this.buttonEventDetails[id]) {\n this.buttonEventDetails[id] = {id: id, state: this.buttonStates[id]};\n }\n\n buttonState = gamepad.buttons[id];\n this.handleButton(id, buttonState);\n }\n // Check axes.\n this.handleAxes();\n },\n\n /**\n * Handle presses and touches for a single button.\n *\n * @param {number} id - Index of button in Gamepad button array.\n * @param {number} buttonState - Value of button state from 0 to 1.\n * @returns {boolean} Whether button has changed in any way.\n */\n handleButton: function (id, buttonState) {\n var changed;\n changed = this.handlePress(id, buttonState) |\n this.handleTouch(id, buttonState) |\n this.handleValue(id, buttonState);\n if (!changed) { return false; }\n this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false);\n return true;\n },\n\n /**\n * An axis is an array of values from -1 (up, left) to 1 (down, right).\n * Compare each component of the axis to the previous value to determine change.\n *\n * @returns {boolean} Whether axes changed.\n */\n handleAxes: function () {\n var changed = false;\n var controllerAxes = this.controller.gamepad.axes;\n var i;\n var previousAxis = this.axis;\n var changedAxes = this.changedAxes;\n\n // Check if axis changed.\n this.changedAxes.length = 0;\n for (i = 0; i < controllerAxes.length; ++i) {\n changedAxes.push(previousAxis[i] !== controllerAxes[i]);\n if (changedAxes[i]) { changed = true; }\n }\n if (!changed) { return false; }\n\n this.axis.length = 0;\n for (i = 0; i < controllerAxes.length; i++) {\n this.axis.push(controllerAxes[i]);\n }\n this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false);\n return true;\n },\n\n /**\n * Determine whether a button press has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button press state changed.\n */\n handlePress: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.pressed === previousButtonState.pressed) { return false; }\n\n evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.pressed = buttonState.pressed;\n return true;\n },\n\n /**\n * Determine whether a button touch has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button touch state changed.\n */\n handleTouch: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.touched === previousButtonState.touched) { return false; }\n\n evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.touched = buttonState.touched;\n return true;\n },\n\n /**\n * Determine whether a button value has changed.\n *\n * @param {string} id - Id of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button value changed.\n */\n handleValue: function (id, buttonState) {\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.value === previousButtonState.value) { return false; }\n\n previousButtonState.value = buttonState.value;\n return true;\n }\n});\n", - "var registerComponent = require('../core/component').registerComponent;\n\n/**\n * Tracked controls.\n * Abstract controls that decide if the WebVR or WebXR version is going to be applied.\n *\n * @property {number} controller - Index of controller in array returned by Gamepad API.\n * Only used if hand property is not set.\n * @property {string} id - Selected controller among those returned by Gamepad API.\n * @property {number} hand - If multiple controllers found with id, choose the one with the\n * given value for hand. If set, we ignore 'controller' property\n */\nmodule.exports.Component = registerComponent('tracked-controls', {\n schema: {\n autoHide: {default: true},\n controller: {default: -1},\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n idPrefix: {type: 'string', default: ''},\n orientationOffset: {type: 'vec3'},\n // Arm model parameters when not 6DoF.\n armModel: {default: true},\n headElement: {type: 'selector'},\n iterateControllerProfiles: {default: false}\n },\n\n update: function () {\n var data = this.data;\n var el = this.el;\n if (el.sceneEl.hasWebXR) {\n el.setAttribute('tracked-controls-webxr', {\n id: data.id,\n hand: data.hand,\n index: data.controller,\n iterateControllerProfiles: data.iterateControllerProfiles\n });\n } else {\n el.setAttribute('tracked-controls-webvr', data);\n }\n }\n});\n", + "var registerComponent = require('../core/component').registerComponent;\nvar controllerUtils = require('../utils/tracked-controls');\nvar DEFAULT_CAMERA_HEIGHT = require('../constants').DEFAULT_CAMERA_HEIGHT;\nvar THREE = require('../lib/three');\n\nvar DEFAULT_HANDEDNESS = require('../constants').DEFAULT_HANDEDNESS;\n// Vector from eyes to elbow (divided by user height).\nvar EYES_TO_ELBOW = {x: 0.175, y: -0.3, z: -0.03};\n// Vector from eyes to elbow (divided by user height).\nvar FOREARM = {x: 0, y: 0, z: -0.175};\n\n// Due to unfortunate name collision, add empty touches array to avoid Daydream error.\nvar EMPTY_DAYDREAM_TOUCHES = {touches: []};\n\nvar EVENTS = {\n AXISMOVE: 'axismove',\n BUTTONCHANGED: 'buttonchanged',\n BUTTONDOWN: 'buttondown',\n BUTTONUP: 'buttonup',\n TOUCHSTART: 'touchstart',\n TOUCHEND: 'touchend'\n};\n\n/**\n * Tracked controls component.\n * Wrap the gamepad API for pose and button states.\n * Select the appropriate controller and apply pose to the entity.\n * Observe button states and emit appropriate events.\n *\n * @property {number} controller - Index of controller in array returned by Gamepad API.\n * Only used if hand property is not set.\n * @property {string} id - Selected controller among those returned by Gamepad API.\n * @property {number} hand - If multiple controllers found with id, choose the one with the\n * given value for hand. If set, we ignore 'controller' property\n */\nmodule.exports.Component = registerComponent('tracked-controls-webvr', {\n schema: {\n autoHide: {default: true},\n controller: {default: 0},\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n idPrefix: {type: 'string', default: ''},\n orientationOffset: {type: 'vec3'},\n // Arm model parameters when not 6DoF.\n armModel: {default: false},\n headElement: {type: 'selector'}\n },\n\n init: function () {\n // Copy variables back to tracked-controls for backwards compatibility.\n // Some 3rd components rely on them.\n this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0];\n this.buttonStates = this.el.components['tracked-controls'].buttonStates = {};\n this.changedAxes = [];\n this.targetControllerNumber = this.data.controller;\n\n this.axisMoveEventDetail = {axis: this.axis, changed: this.changedAxes};\n this.deltaControllerPosition = new THREE.Vector3();\n this.controllerQuaternion = new THREE.Quaternion();\n this.controllerEuler = new THREE.Euler();\n\n this.updateGamepad();\n\n this.buttonEventDetails = {};\n },\n\n tick: function (time, delta) {\n var mesh = this.el.getObject3D('mesh');\n // Update mesh animations.\n if (mesh && mesh.update) { mesh.update(delta / 1000); }\n this.updateGamepad();\n this.updatePose();\n this.updateButtons();\n },\n\n /**\n * Return default user height to use for non-6DOF arm model.\n */\n defaultUserHeight: function () {\n return DEFAULT_CAMERA_HEIGHT;\n },\n\n /**\n * Return head element to use for non-6DOF arm model.\n */\n getHeadElement: function () {\n return this.data.headElement || this.el.sceneEl.camera.el;\n },\n\n /**\n * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`)\n */\n updateGamepad: function () {\n var data = this.data;\n var controller = controllerUtils.findMatchingControllerWebVR(\n this.system.controllers,\n data.id,\n data.idPrefix,\n data.hand,\n data.controller\n );\n\n this.controller = controller;\n // Legacy handle to the controller for old components.\n this.el.components['tracked-controls'].controller = controller;\n\n if (this.data.autoHide) { this.el.object3D.visible = !!this.controller; }\n },\n\n /**\n * Applies an artificial arm model to simulate elbow to wrist positioning\n * based on the orientation of the controller.\n *\n * @param {object} controllerPosition - Existing vector to update with controller position.\n */\n applyArmModel: function (controllerPosition) {\n // Use controllerPosition and deltaControllerPosition to avoid creating variables.\n var controller = this.controller;\n var controllerEuler = this.controllerEuler;\n var controllerQuaternion = this.controllerQuaternion;\n var deltaControllerPosition = this.deltaControllerPosition;\n var hand;\n var headEl;\n var headObject3D;\n var pose;\n var userHeight;\n\n headEl = this.getHeadElement();\n headObject3D = headEl.object3D;\n userHeight = this.defaultUserHeight();\n\n pose = controller.pose;\n hand = (controller ? controller.hand : undefined) || DEFAULT_HANDEDNESS;\n\n // Use camera position as head position.\n controllerPosition.copy(headObject3D.position);\n // Set offset for degenerate \"arm model\" to elbow.\n deltaControllerPosition.set(\n EYES_TO_ELBOW.x * (hand === 'left' ? -1 : hand === 'right' ? 1 : 0),\n EYES_TO_ELBOW.y, // Lower than our eyes.\n EYES_TO_ELBOW.z); // Slightly out in front.\n // Scale offset by user height.\n deltaControllerPosition.multiplyScalar(userHeight);\n // Apply camera Y rotation (not X or Z, so you can look down at your hand).\n deltaControllerPosition.applyAxisAngle(headObject3D.up, headObject3D.rotation.y);\n // Apply rotated offset to position.\n controllerPosition.add(deltaControllerPosition);\n\n // Set offset for degenerate \"arm model\" forearm. Forearm sticking out from elbow.\n deltaControllerPosition.set(FOREARM.x, FOREARM.y, FOREARM.z);\n // Scale offset by user height.\n deltaControllerPosition.multiplyScalar(userHeight);\n // Apply controller X/Y rotation (tilting up/down/left/right is usually moving the arm).\n if (pose.orientation) {\n controllerQuaternion.fromArray(pose.orientation);\n } else {\n controllerQuaternion.copy(headObject3D.quaternion);\n }\n controllerEuler.setFromQuaternion(controllerQuaternion);\n controllerEuler.set(controllerEuler.x, controllerEuler.y, 0);\n deltaControllerPosition.applyEuler(controllerEuler);\n // Apply rotated offset to position.\n controllerPosition.add(deltaControllerPosition);\n },\n\n /**\n * Read pose from controller (from Gamepad API), apply transforms, apply to entity.\n */\n updatePose: function () {\n var controller = this.controller;\n var data = this.data;\n var object3D = this.el.object3D;\n var pose;\n var vrDisplay = this.system.vrDisplay;\n var standingMatrix;\n\n if (!controller) { return; }\n\n // Compose pose from Gamepad.\n pose = controller.pose;\n\n if (pose.position) {\n object3D.position.fromArray(pose.position);\n } else {\n // Controller not 6DOF, apply arm model.\n if (data.armModel) { this.applyArmModel(object3D.position); }\n }\n\n if (pose.orientation) {\n object3D.quaternion.fromArray(pose.orientation);\n }\n\n // Apply transforms, if 6DOF and in VR.\n if (vrDisplay && pose.position) {\n standingMatrix = this.el.sceneEl.renderer.xr.getStandingMatrix();\n object3D.matrix.compose(object3D.position, object3D.quaternion, object3D.scale);\n object3D.matrix.multiplyMatrices(standingMatrix, object3D.matrix);\n object3D.matrix.decompose(object3D.position, object3D.quaternion, object3D.scale);\n }\n\n object3D.rotateX(this.data.orientationOffset.x * THREE.Math.DEG2RAD);\n object3D.rotateY(this.data.orientationOffset.y * THREE.Math.DEG2RAD);\n object3D.rotateZ(this.data.orientationOffset.z * THREE.Math.DEG2RAD);\n },\n\n /**\n * Handle button changes including axes, presses, touches, values.\n */\n updateButtons: function () {\n var buttonState;\n var controller = this.controller;\n var id;\n\n if (!controller) { return; }\n\n // Check every button.\n for (id = 0; id < controller.buttons.length; ++id) {\n // Initialize button state.\n if (!this.buttonStates[id]) {\n this.buttonStates[id] = {pressed: false, touched: false, value: 0};\n }\n if (!this.buttonEventDetails[id]) {\n this.buttonEventDetails[id] = {id: id, state: this.buttonStates[id]};\n }\n\n buttonState = controller.buttons[id];\n this.handleButton(id, buttonState);\n }\n // Check axes.\n this.handleAxes();\n },\n\n /**\n * Handle presses and touches for a single button.\n *\n * @param {number} id - Index of button in Gamepad button array.\n * @param {number} buttonState - Value of button state from 0 to 1.\n * @returns {boolean} Whether button has changed in any way.\n */\n handleButton: function (id, buttonState) {\n var changed;\n changed = this.handlePress(id, buttonState) |\n this.handleTouch(id, buttonState) |\n this.handleValue(id, buttonState);\n if (!changed) { return false; }\n this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false);\n return true;\n },\n\n /**\n * An axis is an array of values from -1 (up, left) to 1 (down, right).\n * Compare each component of the axis to the previous value to determine change.\n *\n * @returns {boolean} Whether axes changed.\n */\n handleAxes: function () {\n var changed = false;\n var controllerAxes = this.controller.axes;\n var i;\n var previousAxis = this.axis;\n var changedAxes = this.changedAxes;\n\n // Check if axis changed.\n this.changedAxes.length = 0;\n for (i = 0; i < controllerAxes.length; ++i) {\n changedAxes.push(previousAxis[i] !== controllerAxes[i]);\n if (changedAxes[i]) { changed = true; }\n }\n if (!changed) { return false; }\n\n this.axis.length = 0;\n for (i = 0; i < controllerAxes.length; i++) {\n this.axis.push(controllerAxes[i]);\n }\n this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false);\n return true;\n },\n\n /**\n * Determine whether a button press has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button press state changed.\n */\n handlePress: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.pressed === previousButtonState.pressed) { return false; }\n\n evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.pressed = buttonState.pressed;\n return true;\n },\n\n /**\n * Determine whether a button touch has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button touch state changed.\n */\n handleTouch: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.touched === previousButtonState.touched) { return false; }\n\n evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND;\n this.el.emit(evtName, this.buttonEventDetails[id], false, EMPTY_DAYDREAM_TOUCHES);\n previousButtonState.touched = buttonState.touched;\n return true;\n },\n\n /**\n * Determine whether a button value has changed.\n *\n * @param {string} id - Id of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button value changed.\n */\n handleValue: function (id, buttonState) {\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.value === previousButtonState.value) { return false; }\n\n previousButtonState.value = buttonState.value;\n return true;\n }\n});\n", + "var controllerUtils = require('../utils/tracked-controls');\nvar registerComponent = require('../core/component').registerComponent;\n\nvar EVENTS = {\n AXISMOVE: 'axismove',\n BUTTONCHANGED: 'buttonchanged',\n BUTTONDOWN: 'buttondown',\n BUTTONUP: 'buttonup',\n TOUCHSTART: 'touchstart',\n TOUCHEND: 'touchend'\n};\n\nmodule.exports.Component = registerComponent('tracked-controls-webxr', {\n schema: {\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n index: {type: 'int', default: -1},\n iterateControllerProfiles: {default: false}\n },\n\n init: function () {\n this.addSessionEventListeners = this.addSessionEventListeners.bind(this);\n this.updateController = this.updateController.bind(this);\n this.emitButtonUpEvent = this.emitButtonUpEvent.bind(this);\n this.emitButtonDownEvent = this.emitButtonDownEvent.bind(this);\n\n this.selectEventDetails = {id: 'trigger', state: {pressed: false}};\n this.buttonEventDetails = {};\n this.buttonStates = this.el.components['tracked-controls'].buttonStates = {};\n this.axis = this.el.components['tracked-controls'].axis = [0, 0, 0];\n this.changedAxes = [];\n this.axisMoveEventDetail = {axis: this.axis, changed: this.changedAxes};\n },\n\n play: function () {\n var sceneEl = this.el.sceneEl;\n this.updateController();\n this.addSessionEventListeners();\n sceneEl.addEventListener('enter-vr', this.addSessionEventListeners);\n sceneEl.addEventListener('controllersupdated', this.updateController);\n },\n\n pause: function () {\n var sceneEl = this.el.sceneEl;\n this.removeSessionEventListeners();\n sceneEl.removeEventListener('enter-vr', this.addSessionEventListeners);\n sceneEl.removeEventListener('controllersupdated', this.updateController);\n },\n\n addSessionEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n if (!sceneEl.xrSession) { return; }\n sceneEl.xrSession.addEventListener('selectstart', this.emitButtonDownEvent);\n sceneEl.xrSession.addEventListener('selectend', this.emitButtonUpEvent);\n },\n\n removeSessionEventListeners: function () {\n var sceneEl = this.el.sceneEl;\n if (!sceneEl.xrSession) { return; }\n sceneEl.xrSession.removeEventListener('selectstart', this.emitButtonDownEvent);\n sceneEl.xrSession.removeEventListener('selectend', this.emitButtonUpEvent);\n },\n\n isControllerPresent: function (evt) {\n if (!this.controller || this.controller.gamepad) { return false; }\n if (evt.inputSource.handedness !== 'none' &&\n evt.inputSource.handedness !== this.data.hand) {\n return false;\n }\n return true;\n },\n\n emitButtonDownEvent: function (evt) {\n if (!this.isControllerPresent(evt)) { return; }\n\n this.selectEventDetails.state.pressed = true;\n this.el.emit('buttondown', this.selectEventDetails);\n this.el.emit('buttonchanged', this.selectEventDetails);\n this.el.emit('triggerdown');\n },\n\n emitButtonUpEvent: function (evt) {\n if (!this.isControllerPresent(evt)) { return; }\n\n this.selectEventDetails.state.pressed = false;\n this.el.emit('buttonup', this.selectEventDetails);\n this.el.emit('buttonchanged', this.selectEventDetails);\n this.el.emit('triggerup');\n },\n\n /**\n * Handle update controller match criteria (such as `id`, `idPrefix`, `hand`, `controller`)\n */\n updateController: function () {\n this.controller = controllerUtils.findMatchingControllerWebXR(\n this.system.controllers,\n this.data.id,\n this.data.hand,\n this.data.index,\n this.data.iterateControllerProfiles\n );\n // Legacy handle to the controller for old components.\n this.el.components['tracked-controls'].controller = this.controller;\n\n if (this.data.autoHide) { this.el.object3D.visible = !!this.controller; }\n },\n\n tick: function () {\n var sceneEl = this.el.sceneEl;\n if (!this.controller || !sceneEl.frame || !this.system.referenceSpace) { return; }\n this.pose = sceneEl.frame.getPose(this.controller.targetRaySpace, this.system.referenceSpace);\n this.updatePose();\n this.updateButtons();\n },\n\n updatePose: function () {\n var object3D = this.el.object3D;\n var pose = this.pose;\n if (!pose) { return; }\n object3D.matrix.elements = pose.transform.matrix;\n object3D.matrix.decompose(object3D.position, object3D.rotation, object3D.scale);\n },\n\n /**\n * Handle button changes including axes, presses, touches, values.\n */\n updateButtons: function () {\n var buttonState;\n var id;\n var controller = this.controller;\n var gamepad;\n if (!controller || !controller.gamepad) { return; }\n\n gamepad = controller.gamepad;\n // Check every button.\n for (id = 0; id < gamepad.buttons.length; ++id) {\n // Initialize button state.\n if (!this.buttonStates[id]) {\n this.buttonStates[id] = {pressed: false, touched: false, value: 0};\n }\n if (!this.buttonEventDetails[id]) {\n this.buttonEventDetails[id] = {id: id, state: this.buttonStates[id]};\n }\n\n buttonState = gamepad.buttons[id];\n this.handleButton(id, buttonState);\n }\n // Check axes.\n this.handleAxes();\n },\n\n /**\n * Handle presses and touches for a single button.\n *\n * @param {number} id - Index of button in Gamepad button array.\n * @param {number} buttonState - Value of button state from 0 to 1.\n * @returns {boolean} Whether button has changed in any way.\n */\n handleButton: function (id, buttonState) {\n var changed;\n changed = this.handlePress(id, buttonState) |\n this.handleTouch(id, buttonState) |\n this.handleValue(id, buttonState);\n if (!changed) { return false; }\n this.el.emit(EVENTS.BUTTONCHANGED, this.buttonEventDetails[id], false);\n return true;\n },\n\n /**\n * An axis is an array of values from -1 (up, left) to 1 (down, right).\n * Compare each component of the axis to the previous value to determine change.\n *\n * @returns {boolean} Whether axes changed.\n */\n handleAxes: function () {\n var changed = false;\n var controllerAxes = this.controller.gamepad.axes;\n var i;\n var previousAxis = this.axis;\n var changedAxes = this.changedAxes;\n\n // Check if axis changed.\n this.changedAxes.length = 0;\n for (i = 0; i < controllerAxes.length; ++i) {\n changedAxes.push(previousAxis[i] !== controllerAxes[i]);\n if (changedAxes[i]) { changed = true; }\n }\n if (!changed) { return false; }\n\n this.axis.length = 0;\n for (i = 0; i < controllerAxes.length; i++) {\n this.axis.push(controllerAxes[i]);\n }\n this.el.emit(EVENTS.AXISMOVE, this.axisMoveEventDetail, false);\n return true;\n },\n\n /**\n * Determine whether a button press has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button press state changed.\n */\n handlePress: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.pressed === previousButtonState.pressed) { return false; }\n\n evtName = buttonState.pressed ? EVENTS.BUTTONDOWN : EVENTS.BUTTONUP;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.pressed = buttonState.pressed;\n return true;\n },\n\n /**\n * Determine whether a button touch has occured and emit events as appropriate.\n *\n * @param {string} id - ID of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button touch state changed.\n */\n handleTouch: function (id, buttonState) {\n var evtName;\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.touched === previousButtonState.touched) { return false; }\n\n evtName = buttonState.touched ? EVENTS.TOUCHSTART : EVENTS.TOUCHEND;\n this.el.emit(evtName, this.buttonEventDetails[id], false);\n previousButtonState.touched = buttonState.touched;\n return true;\n },\n\n /**\n * Determine whether a button value has changed.\n *\n * @param {string} id - Id of the button to check.\n * @param {object} buttonState - State of the button to check.\n * @returns {boolean} Whether button value changed.\n */\n handleValue: function (id, buttonState) {\n var previousButtonState = this.buttonStates[id];\n\n // Not changed.\n if (buttonState.value === previousButtonState.value) { return false; }\n\n previousButtonState.value = buttonState.value;\n return true;\n }\n});\n", + "var registerComponent = require('../core/component').registerComponent;\n\n/**\n * Tracked controls.\n * Abstract controls that decide if the WebVR or WebXR version is going to be applied.\n *\n * @property {number} controller - Index of controller in array returned by Gamepad API.\n * Only used if hand property is not set.\n * @property {string} id - Selected controller among those returned by Gamepad API.\n * @property {number} hand - If multiple controllers found with id, choose the one with the\n * given value for hand. If set, we ignore 'controller' property\n */\nmodule.exports.Component = registerComponent('tracked-controls', {\n schema: {\n autoHide: {default: true},\n controller: {default: -1},\n id: {type: 'string', default: ''},\n hand: {type: 'string', default: ''},\n idPrefix: {type: 'string', default: ''},\n orientationOffset: {type: 'vec3'},\n // Arm model parameters when not 6DoF.\n armModel: {default: false},\n headElement: {type: 'selector'},\n iterateControllerProfiles: {default: false}\n },\n\n update: function () {\n var data = this.data;\n var el = this.el;\n if (el.sceneEl.hasWebXR) {\n el.setAttribute('tracked-controls-webxr', {\n id: data.id,\n hand: data.hand,\n index: data.controller,\n iterateControllerProfiles: data.iterateControllerProfiles\n });\n } else {\n el.setAttribute('tracked-controls-webvr', data);\n }\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\n\n/**\n * Visibility component.\n */\nmodule.exports.Component = registerComponent('visible', {\n schema: {default: true},\n\n update: function () {\n this.el.object3D.visible = this.data;\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar VIVE_CONTROLLER_MODEL_OBJ_URL = 'https://cdn.aframe.io/controllers/vive/vr_controller_vive.obj';\nvar VIVE_CONTROLLER_MODEL_OBJ_MTL = 'https://cdn.aframe.io/controllers/vive/vr_controller_vive.mtl';\n\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'htc-vive-controller-mv';\nvar GAMEPAD_ID_WEBVR = 'OpenVR ';\n\n// Prefix for Gen1 and Gen2 Oculus Touch Controllers.\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\n/**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger (intensity value from 0.5 to 1)\n * 2 - grip\n * 3 - menu (dispatch but better for menu options)\n * 4 - system (never dispatched on this layer)\n */\nvar INPUT_MAPPING_WEBVR = {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'trigger', 'grip', 'menu', 'system']\n};\n\n/**\n * Button IDs:\n * 0 - trigger\n * 1 - squeeze\n * 2 - touchpad\n * 3 - none (dispatch but better for menu options)\n * 4 - menu (never dispatched on this layer)\n *\n * Axis:\n * 0 - touchpad x axis\n * 1 - touchpad y axis\n * Reference: https://github.com/immersive-web/webxr-input-profiles/blob/master/packages/registry/profiles/htc/htc-vive.json\n */\nvar INPUT_MAPPING_WEBXR = {\n axes: {thumbstick: [0, 1]},\n buttons: ['trigger', 'grip', 'trackpad', 'none', 'menu']\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Vive controls.\n * Interface with Vive controllers and map Gamepad events to controller buttons:\n * trackpad, trigger, grip, menu, system\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('vive-controls', {\n schema: {\n hand: {default: 'left'},\n buttonColor: {type: 'color', default: '#FAFAFA'}, // Off-white.\n buttonHighlightColor: {type: 'color', default: '#22D1EE'}, // Light blue.\n model: {default: true},\n orientationOffset: {type: 'vec3'}\n },\n\n mapping: INPUT_MAPPING,\n\n init: function () {\n var self = this;\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.previousButtonValues = {};\n this.rendererSystem = this.el.sceneEl.systems.renderer;\n\n this.bindMethods();\n },\n\n update: function () {\n var data = this.data;\n this.controllerIndex = data.hand === 'right' ? 0 : data.hand === 'left' ? 1 : 2;\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n },\n\n /**\n * Once OpenVR returns correct hand data in supporting browsers, we can use hand property.\n * var isPresent = checkControllerPresentAndSetup(this.el.sceneEl, GAMEPAD_ID_PREFIX,\n { hand: data.hand });\n * Until then, use hardcoded index.\n */\n checkIfControllerPresent: function () {\n var data = this.data;\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, {index: this.controllerIndex, hand: data.hand});\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n\n // If we have an OpenVR Gamepad, use the fixed mapping.\n el.setAttribute('tracked-controls', {\n idPrefix: GAMEPAD_ID_PREFIX,\n hand: data.hand,\n controller: this.controllerIndex,\n orientationOffset: data.orientationOffset\n });\n\n // Load model.\n if (!this.data.model) { return; }\n this.el.setAttribute('obj-model', {\n obj: VIVE_CONTROLLER_MODEL_OBJ_URL,\n mtl: VIVE_CONTROLLER_MODEL_OBJ_MTL\n });\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n /**\n * Rotate the trigger button based on how hard the trigger is pressed.\n */\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n var buttonMeshes = this.buttonMeshes;\n var analogValue;\n\n if (!button) { return; }\n\n if (button === 'trigger') {\n analogValue = evt.detail.state.value;\n // Update trigger rotation depending on button value.\n if (buttonMeshes && buttonMeshes.trigger) {\n buttonMeshes.trigger.rotation.x = -analogValue * (Math.PI / 12);\n }\n }\n\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onModelLoaded: function (evt) {\n var buttonMeshes;\n var controllerObject3D = evt.detail.model;\n var self = this;\n\n if (!this.data.model) { return; }\n\n // Store button meshes object to be able to change their colors.\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.grip = {\n left: controllerObject3D.getObjectByName('leftgrip'),\n right: controllerObject3D.getObjectByName('rightgrip')\n };\n buttonMeshes.menu = controllerObject3D.getObjectByName('menubutton');\n buttonMeshes.system = controllerObject3D.getObjectByName('systembutton');\n buttonMeshes.trackpad = controllerObject3D.getObjectByName('touchpad');\n buttonMeshes.trigger = controllerObject3D.getObjectByName('trigger');\n\n // Set default colors.\n Object.keys(buttonMeshes).forEach(function (buttonName) {\n self.setButtonColor(buttonName, self.data.buttonColor);\n });\n\n // Offset pivot point.\n controllerObject3D.position.set(0, -0.015, 0.04);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n var color;\n var isTouch;\n if (!this.data.model) { return; }\n\n isTouch = evtName.indexOf('touch') !== -1;\n // Don't change color for trackpad touch.\n if (isTouch) { return; }\n\n // Update colors.\n color = evtName === 'up' ? this.data.buttonColor : this.data.buttonHighlightColor;\n this.setButtonColor(buttonName, color);\n },\n\n setButtonColor: function (buttonName, color) {\n var buttonMeshes = this.buttonMeshes;\n var rendererSystem = this.rendererSystem;\n\n if (!buttonMeshes) { return; }\n\n // Need to do both left and right sides for grip.\n if (buttonName === 'grip') {\n buttonMeshes.grip.left.material.color.set(color);\n buttonMeshes.grip.right.material.color.set(color);\n rendererSystem.applyColorCorrection(buttonMeshes.grip.left.material.color);\n rendererSystem.applyColorCorrection(buttonMeshes.grip.right.material.color);\n return;\n }\n buttonMeshes[buttonName].material.color.set(color);\n rendererSystem.applyColorCorrection(buttonMeshes[buttonName].material.color);\n }\n});\n", "var registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar GAMEPAD_ID_PREFIX = 'HTC Vive Focus';\n\nvar VIVE_FOCUS_CONTROLLER_MODEL_URL = 'https://cdn.aframe.io/controllers/vive/focus-controller/focus-controller.gltf';\n\n/**\n * Vive Focus controls.\n * Interface with Vive Focus controller and map Gamepad events to\n * controller buttons: trackpad, trigger\n * Load a controller model and highlight the pressed buttons.\n */\nmodule.exports.Component = registerComponent('vive-focus-controls', {\n schema: {\n hand: {default: ''}, // This informs the degenerate arm model.\n buttonTouchedColor: {type: 'color', default: '#BBBBBB'},\n buttonHighlightColor: {type: 'color', default: '#7A7A7A'},\n model: {default: true},\n orientationOffset: {type: 'vec3'},\n armModel: {default: true}\n },\n\n /**\n * Button IDs:\n * 0 - trackpad\n * 1 - trigger\n */\n mapping: {\n axes: {trackpad: [0, 1]},\n buttons: ['trackpad', 'trigger']\n },\n\n bindMethods: function () {\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.removeControllersUpdateListener = bind(this.removeControllersUpdateListener, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.bindMethods();\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('model-loaded', this.onModelLoaded);\n el.addEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = true;\n this.addControllersUpdateListener();\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n el.removeEventListener('axismove', this.onAxisMoved);\n this.controllerEventsActive = false;\n this.removeControllersUpdateListener();\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX,\n this.data.hand ? {hand: this.data.hand} : {});\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n injectTrackedControls: function () {\n var el = this.el;\n var data = this.data;\n el.setAttribute('tracked-controls', {\n armModel: data.armModel,\n idPrefix: GAMEPAD_ID_PREFIX,\n orientationOffset: data.orientationOffset\n });\n if (!this.data.model) { return; }\n this.el.setAttribute('gltf-model', VIVE_FOCUS_CONTROLLER_MODEL_URL);\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onModelLoaded: function (evt) {\n var controllerObject3D = evt.detail.model;\n var buttonMeshes;\n\n if (!this.data.model) { return; }\n buttonMeshes = this.buttonMeshes = {};\n buttonMeshes.trigger = controllerObject3D.getObjectByName('BumperKey');\n buttonMeshes.triggerPressed = controllerObject3D.getObjectByName('BumperKey_Press');\n if (buttonMeshes.triggerPressed) {\n buttonMeshes.triggerPressed.visible = false;\n }\n buttonMeshes.trackpad = controllerObject3D.getObjectByName('TouchPad');\n buttonMeshes.trackpadPressed = controllerObject3D.getObjectByName('TouchPad_Press');\n if (buttonMeshes.trackpadPressed) {\n buttonMeshes.trackpadPressed.visible = false;\n }\n },\n\n // No analog buttons, only emits 0/1 values\n onButtonChanged: function (evt) {\n var button = this.mapping.buttons[evt.detail.id];\n if (!button) return;\n // Pass along changed event with button state, using button mapping for convenience.\n this.el.emit(button + 'changed', evt.detail.state);\n },\n\n onAxisMoved: function (evt) {\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n updateModel: function (buttonName, evtName) {\n if (!this.data.model) { return; }\n this.updateButtonModel(buttonName, evtName);\n },\n\n updateButtonModel: function (buttonName, state) {\n var buttonMeshes = this.buttonMeshes;\n var pressedName = buttonName + 'Pressed';\n if (!buttonMeshes || !buttonMeshes[buttonName] || !buttonMeshes[pressedName]) {\n return;\n }\n var color;\n switch (state) {\n case 'down':\n color = this.data.buttonHighlightColor;\n break;\n case 'touchstart':\n color = this.data.buttonTouchedColor;\n break;\n }\n if (color) {\n buttonMeshes[pressedName].material.color.set(color);\n }\n buttonMeshes[pressedName].visible = !!color;\n buttonMeshes[buttonName].visible = !color;\n }\n});\n", "var KEYCODE_TO_CODE = require('../constants').keyboardevent.KEYCODE_TO_CODE;\nvar registerComponent = require('../core/component').registerComponent;\nvar THREE = require('../lib/three');\nvar utils = require('../utils/');\n\nvar bind = utils.bind;\nvar shouldCaptureKeyEvent = utils.shouldCaptureKeyEvent;\n\nvar CLAMP_VELOCITY = 0.00001;\nvar MAX_DELTA = 0.2;\nvar KEYS = [\n 'KeyW', 'KeyA', 'KeyS', 'KeyD',\n 'ArrowUp', 'ArrowLeft', 'ArrowRight', 'ArrowDown'\n];\n\n/**\n * WASD component to control entities using WASD keys.\n */\nmodule.exports.Component = registerComponent('wasd-controls', {\n schema: {\n acceleration: {default: 65},\n adAxis: {default: 'x', oneOf: ['x', 'y', 'z']},\n adEnabled: {default: true},\n adInverted: {default: false},\n enabled: {default: true},\n fly: {default: false},\n wsAxis: {default: 'z', oneOf: ['x', 'y', 'z']},\n wsEnabled: {default: true},\n wsInverted: {default: false}\n },\n\n init: function () {\n // To keep track of the pressed keys.\n this.keys = {};\n this.easing = 1.1;\n\n this.velocity = new THREE.Vector3();\n\n // Bind methods and add event listeners.\n this.onBlur = bind(this.onBlur, this);\n this.onFocus = bind(this.onFocus, this);\n this.onKeyDown = bind(this.onKeyDown, this);\n this.onKeyUp = bind(this.onKeyUp, this);\n this.onVisibilityChange = bind(this.onVisibilityChange, this);\n this.attachVisibilityEventListeners();\n },\n\n tick: function (time, delta) {\n var data = this.data;\n var el = this.el;\n var velocity = this.velocity;\n\n if (!velocity[data.adAxis] && !velocity[data.wsAxis] &&\n isEmptyObject(this.keys)) { return; }\n\n // Update velocity.\n delta = delta / 1000;\n this.updateVelocity(delta);\n\n if (!velocity[data.adAxis] && !velocity[data.wsAxis]) { return; }\n\n // Get movement vector and translate position.\n el.object3D.position.add(this.getMovementVector(delta));\n },\n\n remove: function () {\n this.removeKeyEventListeners();\n this.removeVisibilityEventListeners();\n },\n\n play: function () {\n this.attachKeyEventListeners();\n },\n\n pause: function () {\n this.keys = {};\n this.removeKeyEventListeners();\n },\n\n updateVelocity: function (delta) {\n var acceleration;\n var adAxis;\n var adSign;\n var data = this.data;\n var keys = this.keys;\n var velocity = this.velocity;\n var wsAxis;\n var wsSign;\n\n adAxis = data.adAxis;\n wsAxis = data.wsAxis;\n\n // If FPS too low, reset velocity.\n if (delta > MAX_DELTA) {\n velocity[adAxis] = 0;\n velocity[wsAxis] = 0;\n return;\n }\n\n // https://gamedev.stackexchange.com/questions/151383/frame-rate-independant-movement-with-acceleration\n var scaledEasing = Math.pow(1 / this.easing, delta * 60);\n // Velocity Easing.\n if (velocity[adAxis] !== 0) {\n velocity[adAxis] -= velocity[adAxis] * scaledEasing;\n }\n if (velocity[wsAxis] !== 0) {\n velocity[wsAxis] -= velocity[wsAxis] * scaledEasing;\n }\n\n // Clamp velocity easing.\n if (Math.abs(velocity[adAxis]) < CLAMP_VELOCITY) { velocity[adAxis] = 0; }\n if (Math.abs(velocity[wsAxis]) < CLAMP_VELOCITY) { velocity[wsAxis] = 0; }\n\n if (!data.enabled) { return; }\n\n // Update velocity using keys pressed.\n acceleration = data.acceleration;\n if (data.adEnabled) {\n adSign = data.adInverted ? -1 : 1;\n if (keys.KeyA || keys.ArrowLeft) { velocity[adAxis] -= adSign * acceleration * delta; }\n if (keys.KeyD || keys.ArrowRight) { velocity[adAxis] += adSign * acceleration * delta; }\n }\n if (data.wsEnabled) {\n wsSign = data.wsInverted ? -1 : 1;\n if (keys.KeyW || keys.ArrowUp) { velocity[wsAxis] -= wsSign * acceleration * delta; }\n if (keys.KeyS || keys.ArrowDown) { velocity[wsAxis] += wsSign * acceleration * delta; }\n }\n },\n\n getMovementVector: (function () {\n var directionVector = new THREE.Vector3(0, 0, 0);\n var rotationEuler = new THREE.Euler(0, 0, 0, 'YXZ');\n\n return function (delta) {\n var rotation = this.el.getAttribute('rotation');\n var velocity = this.velocity;\n var xRotation;\n\n directionVector.copy(velocity);\n directionVector.multiplyScalar(delta);\n\n // Absolute.\n if (!rotation) { return directionVector; }\n\n xRotation = this.data.fly ? rotation.x : 0;\n\n // Transform direction relative to heading.\n rotationEuler.set(THREE.Math.degToRad(xRotation), THREE.Math.degToRad(rotation.y), 0);\n directionVector.applyEuler(rotationEuler);\n return directionVector;\n };\n })(),\n\n attachVisibilityEventListeners: function () {\n window.addEventListener('blur', this.onBlur);\n window.addEventListener('focus', this.onFocus);\n document.addEventListener('visibilitychange', this.onVisibilityChange);\n },\n\n removeVisibilityEventListeners: function () {\n window.removeEventListener('blur', this.onBlur);\n window.removeEventListener('focus', this.onFocus);\n document.removeEventListener('visibilitychange', this.onVisibilityChange);\n },\n\n attachKeyEventListeners: function () {\n window.addEventListener('keydown', this.onKeyDown);\n window.addEventListener('keyup', this.onKeyUp);\n },\n\n removeKeyEventListeners: function () {\n window.removeEventListener('keydown', this.onKeyDown);\n window.removeEventListener('keyup', this.onKeyUp);\n },\n\n onBlur: function () {\n this.pause();\n },\n\n onFocus: function () {\n this.play();\n },\n\n onVisibilityChange: function () {\n if (document.hidden) {\n this.onBlur();\n } else {\n this.onFocus();\n }\n },\n\n onKeyDown: function (event) {\n var code;\n if (!shouldCaptureKeyEvent(event)) { return; }\n code = event.code || KEYCODE_TO_CODE[event.keyCode];\n if (KEYS.indexOf(code) !== -1) { this.keys[code] = true; }\n },\n\n onKeyUp: function (event) {\n var code;\n code = event.code || KEYCODE_TO_CODE[event.keyCode];\n delete this.keys[code];\n }\n});\n\nfunction isEmptyObject (keys) {\n var key;\n for (key in keys) { return false; }\n return true;\n}\n", - "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar utils = require('../utils/');\n\nvar debug = utils.debug('components:windows-motion-controls:debug');\nvar warn = utils.debug('components:windows-motion-controls:warn');\n\nvar DEFAULT_HANDEDNESS = require('../constants').DEFAULT_HANDEDNESS;\n\nvar MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/microsoft/';\nvar MODEL_FILENAMES = { left: 'left.glb', right: 'right.glb', default: 'universal.glb' };\n\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'windows-mixed-reality';\nvar GAMEPAD_ID_WEBVR = 'Spatial Controller (Spatial Interaction Source) ';\nvar GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;\n\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\nvar INPUT_MAPPING_WEBVR = {\n // A-Frame specific semantic axis names\n axes: {'thumbstick': [0, 1], 'trackpad': [2, 3]},\n // A-Frame specific semantic button names\n buttons: ['thumbstick', 'trigger', 'grip', 'menu', 'trackpad'],\n // A mapping of the semantic name to node name in the glTF model file,\n // that should be transformed by axis value.\n // This array mirrors the browser Gamepad.axes array, such that\n // the mesh corresponding to axis 0 is in this array index 0.\n axisMeshNames: [\n 'THUMBSTICK_X',\n 'THUMBSTICK_Y',\n 'TOUCHPAD_TOUCH_X',\n 'TOUCHPAD_TOUCH_Y'\n ],\n // A mapping of the semantic name to button node name in the glTF model file,\n // that should be transformed by button value.\n buttonMeshNames: {\n 'trigger': 'SELECT',\n 'menu': 'MENU',\n 'grip': 'GRASP',\n 'thumbstick': 'THUMBSTICK_PRESS',\n 'trackpad': 'TOUCHPAD_PRESS'\n },\n pointingPoseMeshName: 'POINTING_POSE'\n};\n\nvar INPUT_MAPPING_WEBXR = {\n // A-Frame specific semantic axis names\n axes: {'touchpad': [0, 1], 'thumbstick': [2, 3]},\n // A-Frame specific semantic button names\n buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick', 'menu'],\n // A mapping of the semantic name to node name in the glTF model file,\n // that should be transformed by axis value.\n // This array mirrors the browser Gamepad.axes array, such that\n // the mesh corresponding to axis 0 is in this array index 0.\n axisMeshNames: [\n 'TOUCHPAD_TOUCH_X',\n 'TOUCHPAD_TOUCH_X',\n 'THUMBSTICK_X',\n 'THUMBSTICK_Y'\n ],\n // A mapping of the semantic name to button node name in the glTF model file,\n // that should be transformed by button value.\n buttonMeshNames: {\n 'trigger': 'SELECT',\n 'menu': 'MENU',\n 'squeeze': 'GRASP',\n 'thumbstick': 'THUMBSTICK_PRESS',\n 'touchpad': 'TOUCHPAD_PRESS'\n },\n pointingPoseMeshName: 'POINTING_POSE'\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Windows Motion Controller controls.\n * Interface with Windows Motion Controller controllers and map Gamepad events to\n * controller buttons: trackpad, trigger, grip, menu, thumbstick\n * Load a controller model and transform the pressed buttons.\n */\nmodule.exports.Component = registerComponent('windows-motion-controls', {\n schema: {\n hand: {default: DEFAULT_HANDEDNESS},\n // It is possible to have multiple pairs of controllers attached (a pair has both left and right).\n // Set this to 1 to use a controller from the second pair, 2 from the third pair, etc.\n pair: {default: 0},\n // If true, loads the controller glTF asset.\n model: {default: true},\n // If true, will hide the model from the scene if no matching gamepad (based on ID & hand) is connected.\n hideDisconnected: {default: true}\n },\n\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelError = bind(this.onModelError, this);\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n var el = this.el;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.onControllerConnected = function () { self.setModelVisibility(true); };\n this.onControllerDisconnected = function () { self.setModelVisibility(false); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.previousButtonValues = {};\n this.bindMethods();\n\n // Cache for submeshes that we have looked up by name.\n this.loadedMeshInfo = {\n buttonMeshes: null,\n axisMeshes: null\n };\n\n // Pointing poses\n this.rayOrigin = {\n origin: new THREE.Vector3(),\n direction: new THREE.Vector3(0, 0, -1),\n createdFromMesh: false\n };\n\n el.addEventListener('controllerconnected', this.onControllerConnected);\n el.addEventListener('controllerdisconnected', this.onControllerDisconnected);\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('axismove', this.onAxisMoved);\n el.addEventListener('model-error', this.onModelError);\n el.addEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n el.removeEventListener('model-error', this.onModelError);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, {\n hand: this.data.hand,\n index: this.data.pair\n });\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n updateControllerModel: function () {\n // If we do not want to load a model, or, have already loaded the model, emit the controllermodelready event.\n if (!this.data.model || this.rayOrigin.createdFromMesh) {\n this.modelReady();\n return;\n }\n\n var sourceUrl = this.createControllerModelUrl();\n this.loadModel(sourceUrl);\n },\n\n /**\n * Helper function that constructs a URL from the controller ID suffix, for future proofed\n * art assets.\n */\n createControllerModelUrl: function (forceDefault) {\n // Determine the device specific folder based on the ID suffix\n var trackedControlsComponent = this.el.components['tracked-controls'];\n var controller = trackedControlsComponent ? trackedControlsComponent.controller : null;\n var device = 'default';\n var hand = this.data.hand;\n var filename;\n\n if (controller && !window.hasNativeWebXRImplementation) {\n // Read hand directly from the controller, rather than this.data, as in the case that the controller\n // is unhanded this.data will still have 'left' or 'right' (depending on what the user inserted in to the scene).\n // In this case, we want to load the universal model, so need to get the '' from the controller.\n hand = controller.hand;\n\n if (!forceDefault) {\n var match = controller.id.match(GAMEPAD_ID_PATTERN);\n device = ((match && match[0]) || device);\n }\n }\n\n // Hand\n filename = MODEL_FILENAMES[hand] || MODEL_FILENAMES.default;\n\n // Final url\n return MODEL_BASE_URL + device + '/' + filename;\n },\n\n injectTrackedControls: function () {\n var data = this.data;\n this.el.setAttribute('tracked-controls', {\n idPrefix: GAMEPAD_ID_PREFIX,\n controller: data.pair,\n hand: data.hand,\n armModel: false\n });\n\n this.updateControllerModel();\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onModelError: function (evt) {\n var defaultUrl = this.createControllerModelUrl(true);\n if (evt.detail.src !== defaultUrl) {\n warn('Failed to load controller model for device, attempting to load default.');\n this.loadModel(defaultUrl);\n } else {\n warn('Failed to load default controller model.');\n }\n },\n\n loadModel: function (url) {\n // The model is loaded by the gltf-model compoent when this attribute is initially set,\n // removed and re-loaded if the given url changes.\n this.el.setAttribute('gltf-model', 'url(' + url + ')');\n },\n\n onModelLoaded: function (evt) {\n var rootNode = this.controllerModel = evt.detail.model;\n var loadedMeshInfo = this.loadedMeshInfo;\n var i;\n var meshName;\n var mesh;\n var meshInfo;\n\n debug('Processing model');\n\n // Reset the caches\n loadedMeshInfo.buttonMeshes = {};\n loadedMeshInfo.axisMeshes = {};\n\n // Cache our meshes so we aren't traversing the hierarchy per frame\n if (rootNode) {\n // Button Meshes\n for (i = 0; i < this.mapping.buttons.length; i++) {\n meshName = this.mapping.buttonMeshNames[this.mapping.buttons[i]];\n if (!meshName) {\n debug('Skipping unknown button at index: ' + i + ' with mapped name: ' + this.mapping.buttons[i]);\n continue;\n }\n\n mesh = rootNode.getObjectByName(meshName);\n if (!mesh) {\n warn('Missing button mesh with name: ' + meshName);\n continue;\n }\n\n meshInfo = {\n index: i,\n value: getImmediateChildByName(mesh, 'VALUE'),\n pressed: getImmediateChildByName(mesh, 'PRESSED'),\n unpressed: getImmediateChildByName(mesh, 'UNPRESSED')\n };\n if (meshInfo.value && meshInfo.pressed && meshInfo.unpressed) {\n loadedMeshInfo.buttonMeshes[this.mapping.buttons[i]] = meshInfo;\n } else {\n // If we didn't find the mesh, it simply means this button won't have transforms applied as mapped button value changes.\n warn('Missing button submesh under mesh with name: ' + meshName +\n '(VALUE: ' + !!meshInfo.value +\n ', PRESSED: ' + !!meshInfo.pressed +\n ', UNPRESSED:' + !!meshInfo.unpressed +\n ')');\n }\n }\n\n // Axis Meshes\n for (i = 0; i < this.mapping.axisMeshNames.length; i++) {\n meshName = this.mapping.axisMeshNames[i];\n if (!meshName) {\n debug('Skipping unknown axis at index: ' + i);\n continue;\n }\n\n mesh = rootNode.getObjectByName(meshName);\n if (!mesh) {\n warn('Missing axis mesh with name: ' + meshName);\n continue;\n }\n\n meshInfo = {\n index: i,\n value: getImmediateChildByName(mesh, 'VALUE'),\n min: getImmediateChildByName(mesh, 'MIN'),\n max: getImmediateChildByName(mesh, 'MAX')\n };\n if (meshInfo.value && meshInfo.min && meshInfo.max) {\n loadedMeshInfo.axisMeshes[i] = meshInfo;\n } else {\n // If we didn't find the mesh, it simply means this axis won't have transforms applied as mapped axis values change.\n warn('Missing axis submesh under mesh with name: ' + meshName +\n '(VALUE: ' + !!meshInfo.value +\n ', MIN: ' + !!meshInfo.min +\n ', MAX:' + !!meshInfo.max +\n ')');\n }\n }\n\n this.calculateRayOriginFromMesh(rootNode);\n // Determine if the model has to be visible or not.\n this.setModelVisibility();\n }\n\n debug('Model load complete.');\n\n // Look through only immediate children. This will return null if no mesh exists with the given name.\n function getImmediateChildByName (object3d, value) {\n for (var i = 0, l = object3d.children.length; i < l; i++) {\n var obj = object3d.children[i];\n if (obj && obj['name'] === value) {\n return obj;\n }\n }\n return undefined;\n }\n },\n\n calculateRayOriginFromMesh: (function () {\n var quaternion = new THREE.Quaternion();\n return function (rootNode) {\n var mesh;\n\n // Calculate the pointer pose (used for rays), by applying the world transform of th POINTER_POSE node\n // in the glTF (assumes that root node is at world origin)\n this.rayOrigin.origin.set(0, 0, 0);\n this.rayOrigin.direction.set(0, 0, -1);\n this.rayOrigin.createdFromMesh = true;\n\n // Try to read Pointing pose from the source model\n mesh = rootNode.getObjectByName(this.mapping.pointingPoseMeshName);\n if (mesh) {\n var parent = rootNode.parent;\n\n // We need to read pose transforms accumulated from the root of the glTF, not the scene.\n if (parent) {\n rootNode.parent = null;\n rootNode.updateMatrixWorld(true);\n rootNode.parent = parent;\n }\n\n mesh.getWorldPosition(this.rayOrigin.origin);\n mesh.getWorldQuaternion(quaternion);\n this.rayOrigin.direction.applyQuaternion(quaternion);\n\n // Recalculate the world matrices now that the rootNode is re-attached to the parent.\n if (parent) {\n rootNode.updateMatrixWorld(true);\n }\n } else {\n debug('Mesh does not contain pointing origin data, defaulting to none.');\n }\n\n // Emit event stating that our pointing ray is now accurate.\n this.modelReady();\n };\n })(),\n\n lerpAxisTransform: (function () {\n var quaternion = new THREE.Quaternion();\n return function (axis, axisValue) {\n var axisMeshInfo = this.loadedMeshInfo.axisMeshes[axis];\n if (!axisMeshInfo) return;\n\n var min = axisMeshInfo.min;\n var max = axisMeshInfo.max;\n var target = axisMeshInfo.value;\n\n // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)\n var lerpValue = axisValue * 0.5 + 0.5;\n target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, lerpValue));\n target.position.lerpVectors(min.position, max.position, lerpValue);\n };\n })(),\n\n lerpButtonTransform: (function () {\n var quaternion = new THREE.Quaternion();\n return function (buttonName, buttonValue) {\n var buttonMeshInfo = this.loadedMeshInfo.buttonMeshes[buttonName];\n if (!buttonMeshInfo) return;\n\n var min = buttonMeshInfo.unpressed;\n var max = buttonMeshInfo.pressed;\n var target = buttonMeshInfo.value;\n\n target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, buttonValue));\n target.position.lerpVectors(min.position, max.position, buttonValue);\n };\n })(),\n\n modelReady: function () {\n this.el.emit('controllermodelready', {\n name: 'windows-motion-controls',\n model: this.data.model,\n rayOrigin: this.rayOrigin\n });\n },\n\n onButtonChanged: function (evt) {\n var buttonName = this.mapping.buttons[evt.detail.id];\n\n if (buttonName) {\n // Update the button mesh transform\n if (this.loadedMeshInfo && this.loadedMeshInfo.buttonMeshes) {\n this.lerpButtonTransform(buttonName, evt.detail.state.value);\n }\n\n // Only emit events for buttons that we know how to map from index to name\n this.el.emit(buttonName + 'changed', evt.detail.state);\n }\n },\n\n onAxisMoved: function (evt) {\n var numAxes = this.mapping.axisMeshNames.length;\n\n // Only attempt to update meshes if we have valid data.\n if (this.loadedMeshInfo && this.loadedMeshInfo.axisMeshes) {\n for (var axis = 0; axis < numAxes; axis++) {\n // Update the button mesh transform\n this.lerpAxisTransform(axis, evt.detail.axis[axis] || 0.0);\n }\n }\n\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n setModelVisibility: function (visible) {\n var model = this.el.getObject3D('mesh');\n visible = visible !== undefined ? visible : this.modelVisible;\n this.modelVisible = visible;\n if (!model) { return; }\n model.visible = visible;\n }\n});\n", + "/* global THREE */\nvar registerComponent = require('../core/component').registerComponent;\nvar bind = require('../utils/bind');\n\nvar trackedControlsUtils = require('../utils/tracked-controls');\nvar checkControllerPresentAndSetup = trackedControlsUtils.checkControllerPresentAndSetup;\nvar emitIfAxesChanged = trackedControlsUtils.emitIfAxesChanged;\nvar onButtonEvent = trackedControlsUtils.onButtonEvent;\n\nvar utils = require('../utils/');\n\nvar debug = utils.debug('components:windows-motion-controls:debug');\nvar warn = utils.debug('components:windows-motion-controls:warn');\n\nvar DEFAULT_HANDEDNESS = require('../constants').DEFAULT_HANDEDNESS;\n\nvar MODEL_BASE_URL = 'https://cdn.aframe.io/controllers/microsoft/';\nvar MODEL_FILENAMES = { left: 'left.glb', right: 'right.glb', default: 'universal.glb' };\n\nvar isWebXRAvailable = require('../utils/').device.isWebXRAvailable;\n\nvar GAMEPAD_ID_WEBXR = 'windows-mixed-reality';\nvar GAMEPAD_ID_WEBVR = 'Spatial Controller (Spatial Interaction Source) ';\nvar GAMEPAD_ID_PATTERN = /([0-9a-zA-Z]+-[0-9a-zA-Z]+)$/;\n\nvar GAMEPAD_ID_PREFIX = isWebXRAvailable ? GAMEPAD_ID_WEBXR : GAMEPAD_ID_WEBVR;\n\nvar INPUT_MAPPING_WEBVR = {\n // A-Frame specific semantic axis names\n axes: {'thumbstick': [0, 1], 'trackpad': [2, 3]},\n // A-Frame specific semantic button names\n buttons: ['thumbstick', 'trigger', 'grip', 'menu', 'trackpad'],\n // A mapping of the semantic name to node name in the glTF model file,\n // that should be transformed by axis value.\n // This array mirrors the browser Gamepad.axes array, such that\n // the mesh corresponding to axis 0 is in this array index 0.\n axisMeshNames: [\n 'THUMBSTICK_X',\n 'THUMBSTICK_Y',\n 'TOUCHPAD_TOUCH_X',\n 'TOUCHPAD_TOUCH_Y'\n ],\n // A mapping of the semantic name to button node name in the glTF model file,\n // that should be transformed by button value.\n buttonMeshNames: {\n 'trigger': 'SELECT',\n 'menu': 'MENU',\n 'grip': 'GRASP',\n 'thumbstick': 'THUMBSTICK_PRESS',\n 'trackpad': 'TOUCHPAD_PRESS'\n },\n pointingPoseMeshName: 'POINTING_POSE'\n};\n\nvar INPUT_MAPPING_WEBXR = {\n // A-Frame specific semantic axis names\n axes: {'touchpad': [0, 1], 'thumbstick': [2, 3]},\n // A-Frame specific semantic button names\n buttons: ['trigger', 'squeeze', 'touchpad', 'thumbstick', 'menu'],\n // A mapping of the semantic name to node name in the glTF model file,\n // that should be transformed by axis value.\n // This array mirrors the browser Gamepad.axes array, such that\n // the mesh corresponding to axis 0 is in this array index 0.\n axisMeshNames: [\n 'TOUCHPAD_TOUCH_X',\n 'TOUCHPAD_TOUCH_X',\n 'THUMBSTICK_X',\n 'THUMBSTICK_Y'\n ],\n // A mapping of the semantic name to button node name in the glTF model file,\n // that should be transformed by button value.\n buttonMeshNames: {\n 'trigger': 'SELECT',\n 'menu': 'MENU',\n 'squeeze': 'GRASP',\n 'thumbstick': 'THUMBSTICK_PRESS',\n 'touchpad': 'TOUCHPAD_PRESS'\n },\n pointingPoseMeshName: 'POINTING_POSE'\n};\n\nvar INPUT_MAPPING = isWebXRAvailable ? INPUT_MAPPING_WEBXR : INPUT_MAPPING_WEBVR;\n\n/**\n * Windows Motion Controller controls.\n * Interface with Windows Motion Controller controllers and map Gamepad events to\n * controller buttons: trackpad, trigger, grip, menu, thumbstick\n * Load a controller model and transform the pressed buttons.\n */\nmodule.exports.Component = registerComponent('windows-motion-controls', {\n schema: {\n hand: {default: DEFAULT_HANDEDNESS},\n // It is possible to have multiple pairs of controllers attached (a pair has both left and right).\n // Set this to 1 to use a controller from the second pair, 2 from the third pair, etc.\n pair: {default: 0},\n // If true, loads the controller glTF asset.\n model: {default: true},\n // If true, will hide the model from the scene if no matching gamepad (based on ID & hand) is connected.\n hideDisconnected: {default: true}\n },\n\n mapping: INPUT_MAPPING,\n\n bindMethods: function () {\n this.onModelError = bind(this.onModelError, this);\n this.onModelLoaded = bind(this.onModelLoaded, this);\n this.onControllersUpdate = bind(this.onControllersUpdate, this);\n this.checkIfControllerPresent = bind(this.checkIfControllerPresent, this);\n this.onAxisMoved = bind(this.onAxisMoved, this);\n },\n\n init: function () {\n var self = this;\n var el = this.el;\n this.onButtonChanged = bind(this.onButtonChanged, this);\n this.onButtonDown = function (evt) { onButtonEvent(evt.detail.id, 'down', self); };\n this.onButtonUp = function (evt) { onButtonEvent(evt.detail.id, 'up', self); };\n this.onButtonTouchStart = function (evt) { onButtonEvent(evt.detail.id, 'touchstart', self); };\n this.onButtonTouchEnd = function (evt) { onButtonEvent(evt.detail.id, 'touchend', self); };\n this.onControllerConnected = function () { self.setModelVisibility(true); };\n this.onControllerDisconnected = function () { self.setModelVisibility(false); };\n this.controllerPresent = false;\n this.lastControllerCheck = 0;\n this.previousButtonValues = {};\n this.bindMethods();\n\n // Cache for submeshes that we have looked up by name.\n this.loadedMeshInfo = {\n buttonMeshes: null,\n axisMeshes: null\n };\n\n // Pointing poses\n this.rayOrigin = {\n origin: new THREE.Vector3(),\n direction: new THREE.Vector3(0, 0, -1),\n createdFromMesh: false\n };\n\n el.addEventListener('controllerconnected', this.onControllerConnected);\n el.addEventListener('controllerdisconnected', this.onControllerDisconnected);\n },\n\n addEventListeners: function () {\n var el = this.el;\n el.addEventListener('buttonchanged', this.onButtonChanged);\n el.addEventListener('buttondown', this.onButtonDown);\n el.addEventListener('buttonup', this.onButtonUp);\n el.addEventListener('touchstart', this.onButtonTouchStart);\n el.addEventListener('touchend', this.onButtonTouchEnd);\n el.addEventListener('axismove', this.onAxisMoved);\n el.addEventListener('model-error', this.onModelError);\n el.addEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = true;\n },\n\n removeEventListeners: function () {\n var el = this.el;\n el.removeEventListener('buttonchanged', this.onButtonChanged);\n el.removeEventListener('buttondown', this.onButtonDown);\n el.removeEventListener('buttonup', this.onButtonUp);\n el.removeEventListener('touchstart', this.onButtonTouchStart);\n el.removeEventListener('touchend', this.onButtonTouchEnd);\n el.removeEventListener('axismove', this.onAxisMoved);\n el.removeEventListener('model-error', this.onModelError);\n el.removeEventListener('model-loaded', this.onModelLoaded);\n this.controllerEventsActive = false;\n },\n\n checkIfControllerPresent: function () {\n checkControllerPresentAndSetup(this, GAMEPAD_ID_PREFIX, {\n hand: this.data.hand,\n index: this.data.pair,\n iterateControllerProfiles: true\n });\n },\n\n play: function () {\n this.checkIfControllerPresent();\n this.addControllersUpdateListener();\n },\n\n pause: function () {\n this.removeEventListeners();\n this.removeControllersUpdateListener();\n },\n\n updateControllerModel: function () {\n // If we do not want to load a model, or, have already loaded the model, emit the controllermodelready event.\n if (!this.data.model || this.rayOrigin.createdFromMesh) {\n this.modelReady();\n return;\n }\n\n var sourceUrl = this.createControllerModelUrl();\n this.loadModel(sourceUrl);\n },\n\n /**\n * Helper function that constructs a URL from the controller ID suffix, for future proofed\n * art assets.\n */\n createControllerModelUrl: function (forceDefault) {\n // Determine the device specific folder based on the ID suffix\n var trackedControlsComponent = this.el.components['tracked-controls'];\n var controller = trackedControlsComponent ? trackedControlsComponent.controller : null;\n var device = 'default';\n var hand = this.data.hand;\n var filename;\n\n if (controller && !window.hasNativeWebXRImplementation) {\n // Read hand directly from the controller, rather than this.data, as in the case that the controller\n // is unhanded this.data will still have 'left' or 'right' (depending on what the user inserted in to the scene).\n // In this case, we want to load the universal model, so need to get the '' from the controller.\n hand = controller.hand;\n\n if (!forceDefault) {\n var match = controller.id.match(GAMEPAD_ID_PATTERN);\n device = ((match && match[0]) || device);\n }\n }\n\n // Hand\n filename = MODEL_FILENAMES[hand] || MODEL_FILENAMES.default;\n\n // Final url\n return MODEL_BASE_URL + device + '/' + filename;\n },\n\n injectTrackedControls: function () {\n var data = this.data;\n this.el.setAttribute('tracked-controls', {\n idPrefix: GAMEPAD_ID_PREFIX,\n controller: data.pair,\n hand: data.hand,\n armModel: false\n });\n\n this.updateControllerModel();\n },\n\n addControllersUpdateListener: function () {\n this.el.sceneEl.addEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n removeControllersUpdateListener: function () {\n this.el.sceneEl.removeEventListener('controllersupdated', this.onControllersUpdate, false);\n },\n\n onControllersUpdate: function () {\n this.checkIfControllerPresent();\n },\n\n onModelError: function (evt) {\n var defaultUrl = this.createControllerModelUrl(true);\n if (evt.detail.src !== defaultUrl) {\n warn('Failed to load controller model for device, attempting to load default.');\n this.loadModel(defaultUrl);\n } else {\n warn('Failed to load default controller model.');\n }\n },\n\n loadModel: function (url) {\n // The model is loaded by the gltf-model compoent when this attribute is initially set,\n // removed and re-loaded if the given url changes.\n this.el.setAttribute('gltf-model', 'url(' + url + ')');\n },\n\n onModelLoaded: function (evt) {\n var rootNode = this.controllerModel = evt.detail.model;\n var loadedMeshInfo = this.loadedMeshInfo;\n var i;\n var meshName;\n var mesh;\n var meshInfo;\n\n debug('Processing model');\n\n // Reset the caches\n loadedMeshInfo.buttonMeshes = {};\n loadedMeshInfo.axisMeshes = {};\n\n // Cache our meshes so we aren't traversing the hierarchy per frame\n if (rootNode) {\n // Button Meshes\n for (i = 0; i < this.mapping.buttons.length; i++) {\n meshName = this.mapping.buttonMeshNames[this.mapping.buttons[i]];\n if (!meshName) {\n debug('Skipping unknown button at index: ' + i + ' with mapped name: ' + this.mapping.buttons[i]);\n continue;\n }\n\n mesh = rootNode.getObjectByName(meshName);\n if (!mesh) {\n warn('Missing button mesh with name: ' + meshName);\n continue;\n }\n\n meshInfo = {\n index: i,\n value: getImmediateChildByName(mesh, 'VALUE'),\n pressed: getImmediateChildByName(mesh, 'PRESSED'),\n unpressed: getImmediateChildByName(mesh, 'UNPRESSED')\n };\n if (meshInfo.value && meshInfo.pressed && meshInfo.unpressed) {\n loadedMeshInfo.buttonMeshes[this.mapping.buttons[i]] = meshInfo;\n } else {\n // If we didn't find the mesh, it simply means this button won't have transforms applied as mapped button value changes.\n warn('Missing button submesh under mesh with name: ' + meshName +\n '(VALUE: ' + !!meshInfo.value +\n ', PRESSED: ' + !!meshInfo.pressed +\n ', UNPRESSED:' + !!meshInfo.unpressed +\n ')');\n }\n }\n\n // Axis Meshes\n for (i = 0; i < this.mapping.axisMeshNames.length; i++) {\n meshName = this.mapping.axisMeshNames[i];\n if (!meshName) {\n debug('Skipping unknown axis at index: ' + i);\n continue;\n }\n\n mesh = rootNode.getObjectByName(meshName);\n if (!mesh) {\n warn('Missing axis mesh with name: ' + meshName);\n continue;\n }\n\n meshInfo = {\n index: i,\n value: getImmediateChildByName(mesh, 'VALUE'),\n min: getImmediateChildByName(mesh, 'MIN'),\n max: getImmediateChildByName(mesh, 'MAX')\n };\n if (meshInfo.value && meshInfo.min && meshInfo.max) {\n loadedMeshInfo.axisMeshes[i] = meshInfo;\n } else {\n // If we didn't find the mesh, it simply means this axis won't have transforms applied as mapped axis values change.\n warn('Missing axis submesh under mesh with name: ' + meshName +\n '(VALUE: ' + !!meshInfo.value +\n ', MIN: ' + !!meshInfo.min +\n ', MAX:' + !!meshInfo.max +\n ')');\n }\n }\n\n this.calculateRayOriginFromMesh(rootNode);\n // Determine if the model has to be visible or not.\n this.setModelVisibility();\n }\n\n debug('Model load complete.');\n\n // Look through only immediate children. This will return null if no mesh exists with the given name.\n function getImmediateChildByName (object3d, value) {\n for (var i = 0, l = object3d.children.length; i < l; i++) {\n var obj = object3d.children[i];\n if (obj && obj['name'] === value) {\n return obj;\n }\n }\n return undefined;\n }\n },\n\n calculateRayOriginFromMesh: (function () {\n var quaternion = new THREE.Quaternion();\n return function (rootNode) {\n var mesh;\n\n // Calculate the pointer pose (used for rays), by applying the world transform of th POINTER_POSE node\n // in the glTF (assumes that root node is at world origin)\n this.rayOrigin.origin.set(0, 0, 0);\n this.rayOrigin.direction.set(0, 0, -1);\n this.rayOrigin.createdFromMesh = true;\n\n // Try to read Pointing pose from the source model\n mesh = rootNode.getObjectByName(this.mapping.pointingPoseMeshName);\n if (mesh) {\n var parent = rootNode.parent;\n\n // We need to read pose transforms accumulated from the root of the glTF, not the scene.\n if (parent) {\n rootNode.parent = null;\n rootNode.updateMatrixWorld(true);\n rootNode.parent = parent;\n }\n\n mesh.getWorldPosition(this.rayOrigin.origin);\n mesh.getWorldQuaternion(quaternion);\n this.rayOrigin.direction.applyQuaternion(quaternion);\n\n // Recalculate the world matrices now that the rootNode is re-attached to the parent.\n if (parent) {\n rootNode.updateMatrixWorld(true);\n }\n } else {\n debug('Mesh does not contain pointing origin data, defaulting to none.');\n }\n\n // Emit event stating that our pointing ray is now accurate.\n this.modelReady();\n };\n })(),\n\n lerpAxisTransform: (function () {\n var quaternion = new THREE.Quaternion();\n return function (axis, axisValue) {\n var axisMeshInfo = this.loadedMeshInfo.axisMeshes[axis];\n if (!axisMeshInfo) return;\n\n var min = axisMeshInfo.min;\n var max = axisMeshInfo.max;\n var target = axisMeshInfo.value;\n\n // Convert from gamepad value range (-1 to +1) to lerp range (0 to 1)\n var lerpValue = axisValue * 0.5 + 0.5;\n target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, lerpValue));\n target.position.lerpVectors(min.position, max.position, lerpValue);\n };\n })(),\n\n lerpButtonTransform: (function () {\n var quaternion = new THREE.Quaternion();\n return function (buttonName, buttonValue) {\n var buttonMeshInfo = this.loadedMeshInfo.buttonMeshes[buttonName];\n if (!buttonMeshInfo) return;\n\n var min = buttonMeshInfo.unpressed;\n var max = buttonMeshInfo.pressed;\n var target = buttonMeshInfo.value;\n\n target.setRotationFromQuaternion(quaternion.copy(min.quaternion).slerp(max.quaternion, buttonValue));\n target.position.lerpVectors(min.position, max.position, buttonValue);\n };\n })(),\n\n modelReady: function () {\n this.el.emit('controllermodelready', {\n name: 'windows-motion-controls',\n model: this.data.model,\n rayOrigin: this.rayOrigin\n });\n },\n\n onButtonChanged: function (evt) {\n var buttonName = this.mapping.buttons[evt.detail.id];\n\n if (buttonName) {\n // Update the button mesh transform\n if (this.loadedMeshInfo && this.loadedMeshInfo.buttonMeshes) {\n this.lerpButtonTransform(buttonName, evt.detail.state.value);\n }\n\n // Only emit events for buttons that we know how to map from index to name\n this.el.emit(buttonName + 'changed', evt.detail.state);\n }\n },\n\n onAxisMoved: function (evt) {\n var numAxes = this.mapping.axisMeshNames.length;\n\n // Only attempt to update meshes if we have valid data.\n if (this.loadedMeshInfo && this.loadedMeshInfo.axisMeshes) {\n for (var axis = 0; axis < numAxes; axis++) {\n // Update the button mesh transform\n this.lerpAxisTransform(axis, evt.detail.axis[axis] || 0.0);\n }\n }\n\n emitIfAxesChanged(this, this.mapping.axes, evt);\n },\n\n setModelVisibility: function (visible) {\n var model = this.el.getObject3D('mesh');\n visible = visible !== undefined ? visible : this.modelVisible;\n this.modelVisible = visible;\n if (!model) { return; }\n model.visible = visible;\n }\n});\n", "module.exports = {\n AFRAME_INJECTED: 'aframe-injected',\n DEFAULT_CAMERA_HEIGHT: 1.6,\n DEFAULT_HANDEDNESS: 'right',\n keyboardevent: require('./keyboardevent')\n};\n", "module.exports = {\n // Tiny KeyboardEvent.code polyfill.\n KEYCODE_TO_CODE: {\n '38': 'ArrowUp',\n '37': 'ArrowLeft',\n '40': 'ArrowDown',\n '39': 'ArrowRight',\n '87': 'KeyW',\n '65': 'KeyA',\n '83': 'KeyS',\n '68': 'KeyD'\n }\n};\n", "var ANode = require('./a-node');\nvar bind = require('../utils/bind');\nvar debug = require('../utils/debug');\nvar registerElement = require('./a-register-element').registerElement;\nvar THREE = require('../lib/three');\n\nvar fileLoader = new THREE.FileLoader();\nvar warn = debug('core:a-assets:warn');\n\n/**\n * Asset management system. Handles blocking on asset loading.\n */\nmodule.exports = registerElement('a-assets', {\n prototype: Object.create(ANode.prototype, {\n createdCallback: {\n value: function () {\n this.isAssets = true;\n this.fileLoader = fileLoader;\n this.timeout = null;\n }\n },\n\n attachedCallback: {\n value: function () {\n var self = this;\n var i;\n var loaded = [];\n var mediaEl;\n var mediaEls;\n var imgEl;\n var imgEls;\n var timeout;\n\n if (!this.parentNode.isScene) {\n throw new Error(' must be a child of a .');\n }\n\n // Wait for s.\n imgEls = this.querySelectorAll('img');\n for (i = 0; i < imgEls.length; i++) {\n imgEl = fixUpMediaElement(imgEls[i]);\n loaded.push(new Promise(function (resolve, reject) {\n // Set in cache because we won't be needing to call three.js loader if we have.\n // a loaded media element.\n THREE.Cache.files[imgEls[i].getAttribute('src')] = imgEl;\n imgEl.onload = resolve;\n imgEl.onerror = reject;\n }));\n }\n\n // Wait for